From 6d5872823971b309ee829ff4e6a5c02590d5a8cd Mon Sep 17 00:00:00 2001 From: CocoSimone Date: Fri, 10 Feb 2023 01:01:12 +0100 Subject: [PATCH] Allocate only interpreter or dynarec + hopefully fixed some FPU bugs + hopefully it will build in Windows CI :pray: --- external/imgui/CMakeLists.txt | 5 +- external/parallel-rdp/CMakeLists.txt | 10 +- src/CMakeLists.txt | 4 +- src/backend/Core.cpp | 3 +- src/backend/Core.hpp | 30 ++- src/backend/core/Dynarec.cpp | 61 ++++- src/backend/core/Dynarec.hpp | 21 +- src/backend/core/Interpreter.cpp | 4 +- src/backend/core/Interpreter.hpp | 196 ++++++++------- src/backend/core/RSP.hpp | 1 + src/backend/core/dynarec/cop/cop0decode.cpp | 2 +- .../core/dynarec/cop/cop1instructions.cpp | 83 +++--- src/backend/core/dynarec/decode.cpp | 213 ++++++++-------- src/backend/core/dynarec/instructions.cpp | 4 + .../core/interpreter/cop/cop1instructions.cpp | 82 +++--- src/backend/core/interpreter/decode.cpp | 238 +++++++++--------- src/backend/core/interpreter/instructions.cpp | 198 +++++++-------- src/backend/core/registers/Cop1.cpp | 8 +- src/backend/core/rsp/decode.cpp | 1 + src/backend/core/rsp/instructions.cpp | 62 +++++ src/frontend/imgui/Settings.cpp | 9 +- src/frontend/imgui/Window.hpp | 1 + src/main.cpp | 4 - src/utils/MemoryHelpers.hpp | 4 +- 24 files changed, 661 insertions(+), 583 deletions(-) diff --git a/external/imgui/CMakeLists.txt b/external/imgui/CMakeLists.txt index 0851e218..64f65664 100644 --- a/external/imgui/CMakeLists.txt +++ b/external/imgui/CMakeLists.txt @@ -12,10 +12,9 @@ add_library(imgui imgui/backends/imgui_impl_vulkan.h imgui/backends/imgui_impl_vulkan.cpp) - if(WIN32) - add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS) - add_compile_options(/EHa) + target_compile_definitions(imgui PUBLIC NOMINMAX _CRT_SECURE_NO_WARNINGS) + target_compile_options(imgui PUBLIC /EHa) endif() target_include_directories(imgui PUBLIC ../parallel-rdp/parallel-rdp-standalone/volk diff --git a/external/parallel-rdp/CMakeLists.txt b/external/parallel-rdp/CMakeLists.txt index b1e9f342..68325111 100644 --- a/external/parallel-rdp/CMakeLists.txt +++ b/external/parallel-rdp/CMakeLists.txt @@ -44,6 +44,11 @@ add_library(parallel-rdp parallel-rdp-standalone/volk/volk.c ) +if(WIN32) + target_compile_definitions(parallel-rdp PUBLIC NOMINMAX _CRT_SECURE_NO_WARNINGS) + target_compile_options(parallel-rdp PUBLIC /EHa) +endif() + target_compile_definitions(parallel-rdp PUBLIC GRANITE_VULKAN_MT) target_include_directories(parallel-rdp PUBLIC @@ -55,11 +60,6 @@ target_include_directories(parallel-rdp PUBLIC parallel-rdp-standalone/util ) -if(WIN32) - add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS) - add_compile_options(/EHa) -endif() - if(WIN32) target_compile_definitions(parallel-rdp PUBLIC VK_USE_PLATFORM_WIN32_KHR) else() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ec9909ee..a4c16c96 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -76,8 +76,8 @@ else() if(WIN32) target_compile_options(gadolinium PRIVATE /Od) else() - target_compile_options(gadolinium PRIVATE -fsanitize=address) - target_link_options(gadolinium PRIVATE -fsanitize=address) + #target_compile_options(gadolinium PRIVATE -fsanitize=address) + #target_link_options(gadolinium PRIVATE -fsanitize=address) target_compile_options(gadolinium PRIVATE -g) endif() endif() diff --git a/src/backend/Core.cpp b/src/backend/Core.cpp index 9246627b..b9d8939e 100644 --- a/src/backend/Core.cpp +++ b/src/backend/Core.cpp @@ -25,7 +25,7 @@ CartInfo Core::LoadROM(const std::string& rom_) { romLoaded = true; CartInfo cartInfo = mem.LoadROM(rom); - DoPIFHLE(mem, regs, cartInfo); + DoPIFHLE(mem, CpuGetRegs(), cartInfo); return cartInfo; } @@ -33,6 +33,7 @@ CartInfo Core::LoadROM(const std::string& rom_) { void Core::Run(Window& window, float volumeL, float volumeR) { MMIO& mmio = mem.mmio; Controller& controller = mmio.si.controller; + Registers& regs = CpuGetRegs(); for(int field = 0; field < mmio.vi.numFields; field++) { int frameCycles = 0; diff --git a/src/backend/Core.hpp b/src/backend/Core.hpp index c7656fb6..69839051 100644 --- a/src/backend/Core.hpp +++ b/src/backend/Core.hpp @@ -10,7 +10,7 @@ struct Window; namespace n64 { enum class CpuType { - Dynarec, Interpreter + Dynarec, Interpreter, NONE }; struct Core { @@ -24,14 +24,27 @@ struct Core { VI& GetVI() { return mem.mmio.vi; } void CpuReset() { - cpuDynarec.Reset(); - regs.Reset(); + switch(cpuType) { + case CpuType::Dynarec: cpuDynarec->Reset(); break; + case CpuType::Interpreter: cpuInterp->Reset(); break; + case CpuType::NONE: break; + } + } + + Registers& CpuGetRegs() { + switch(cpuType) { + case CpuType::Dynarec: return cpuDynarec->regs; + case CpuType::Interpreter: return cpuInterp->regs; + case CpuType::NONE: + Util::panic("BRUH\n"); + } } int CpuStep() { switch(cpuType) { - case CpuType::Dynarec: return cpuDynarec.Step(mem, regs); - case CpuType::Interpreter: cpuInterp.Step(mem, regs); return 1; + case CpuType::Dynarec: return cpuDynarec->Step(mem); + case CpuType::Interpreter: cpuInterp->Step(mem); return 1; + case CpuType::NONE: return 0; } } @@ -45,9 +58,8 @@ struct Core { bool done = false; std::string rom; Mem mem; - CpuType cpuType = CpuType::Dynarec; - Interpreter cpuInterp; - JIT::Dynarec cpuDynarec; - Registers regs; + CpuType cpuType = CpuType::NONE; + Interpreter* cpuInterp = nullptr; + JIT::Dynarec* cpuDynarec = nullptr; }; } diff --git a/src/backend/core/Dynarec.cpp b/src/backend/core/Dynarec.cpp index 3beb5ec7..52d31636 100644 --- a/src/backend/core/Dynarec.cpp +++ b/src/backend/core/Dynarec.cpp @@ -6,7 +6,8 @@ namespace n64::JIT { namespace fs = std::filesystem; Dynarec::~Dynarec() { - std::free(codeCache); + Util::aligned_free(codeCache); + dump.close(); } Dynarec::Dynarec() : code(CODECACHE_SIZE, codeCache) { @@ -16,21 +17,47 @@ Dynarec::Dynarec() : code(CODECACHE_SIZE, codeCache) { CODECACHE_SIZE, CodeArray::PROTECT_RWE ); + + if(fs::exists("jit.dump")) { + fs::remove("jit.dump"); + } + + dump.open("jit.dump", std::ios::ate | std::ios::binary); + dump.unsetf(std::ios::skipws); } -void Dynarec::Recompile(Registers& regs, Mem& mem, u32 pc) { +inline bool ShouldServiceInterrupt(Registers& regs) { + bool interrupts_pending = (regs.cop0.status.im & regs.cop0.cause.interruptPending) != 0; + bool interrupts_enabled = regs.cop0.status.ie == 1; + bool currently_handling_exception = regs.cop0.status.exl == 1; + bool currently_handling_error = regs.cop0.status.erl == 1; + + return interrupts_pending && interrupts_enabled && + !currently_handling_exception && !currently_handling_error; +} + +inline void CheckCompareInterrupt(MI& mi, Registers& regs) { + regs.cop0.count++; + regs.cop0.count &= 0x1FFFFFFFF; + if(regs.cop0.count == (u64)regs.cop0.compare << 1) { + regs.cop0.cause.ip7 = 1; + UpdateInterrupt(mi, regs); + } +} + +void Dynarec::Recompile(Mem& mem, u32 pc) { bool branch = false, prevBranch = false; u32 startPC = pc; u32 loopPC = pc; Fn block = code.getCurr(); - if(code.getSize() >= CODECACHE_SIZE) { - Util::print("Code cache overflow!\n"); - code.setSize(code.getSize() & (CODECACHE_SIZE - 1)); + if(code.getSize() >= CODECACHE_OVERHEAD) { + Util::debug("Code cache overflow!\n"); + code.setSize(0); InvalidateCache(); } - Util::print("Start of block @ PC {:08X}\n", loopPC); + Util::debug("Start of block @ PC {:08X}\n", loopPC); code.sub(rsp, 8); while(!prevBranch) { @@ -38,9 +65,10 @@ void Dynarec::Recompile(Registers& regs, Mem& mem, u32 pc) { prevBranch = branch; u32 instr = mem.Read32(regs, loopPC, loopPC); - code.mov(rdi, (u64)®s); + emitBreakpoint(); + code.mov(rdi, (uintptr_t)®s); - Util::print("\tInstr: {:08X}, PC: {:08X}\n", instr, loopPC); + Util::debug("\tInstr: {:08X}, PC: {:08X}\n", instr, loopPC); code.mov(r8, qword[rdi + REG_OFFSET(oldPC)]); code.mov(r9, qword[rdi + REG_OFFSET(pc)]); code.mov(r10, qword[rdi + REG_OFFSET(nextPC)]); @@ -53,12 +81,13 @@ void Dynarec::Recompile(Registers& regs, Mem& mem, u32 pc) { loopPC += 4; - branch = Exec(regs, mem, instr); + branch = Exec(mem, instr); } code.add(rsp, 8); code.ret(); - Util::print("End of block @ PC {:08X}, len: {}\n", loopPC, instrInBlock); + Util::debug("End of block @ PC {:08X}, len: {}\n", loopPC, instrInBlock); + dump.write(code.getCode(), code.getSize()); blockCache[startPC >> 20][startPC & 0xFFF] = block; blockCache[startPC >> 20][startPC & 0xFFF](); @@ -68,7 +97,7 @@ void Dynarec::AllocateOuter(u32 pc) { blockCache[pc >> 20] = (Fn*)bumpAlloc(0x1000 * sizeof(Fn)); } -int Dynarec::Step(Mem &mem, Registers& regs) { +int Dynarec::Step(Mem &mem) { instrInBlock = 0; regs.gpr[0] = 0; regs.prevDelaySlot = regs.delaySlot; @@ -83,11 +112,17 @@ int Dynarec::Step(Mem &mem, Registers& regs) { if(blockCache[pc >> 20][pc & 0xfff]) { blockCache[pc >> 20][pc & 0xfff](); } else { - Recompile(regs, mem, pc); + Recompile(mem, pc); } } else { AllocateOuter(pc); - Recompile(regs, mem, pc); + Recompile(mem, pc); + } + + CheckCompareInterrupt(mem.mmio.mi, regs); + + if(ShouldServiceInterrupt(regs)) { + FireException(regs, ExceptionCode::Interrupt, 0, false); } return instrInBlock; diff --git a/src/backend/core/Dynarec.hpp b/src/backend/core/Dynarec.hpp index f8380ae1..ccda7300 100644 --- a/src/backend/core/Dynarec.hpp +++ b/src/backend/core/Dynarec.hpp @@ -2,6 +2,9 @@ #include #include #include +#include + +namespace n64 { struct Cop1; } namespace n64::JIT { using namespace Xbyak; @@ -11,26 +14,30 @@ using Fn = void (*)(); #define GPR_OFFSET(x) ((uintptr_t)®s.gpr[(x)] - (uintptr_t)®s) #define REG_OFFSET(kind) ((uintptr_t)®s.kind - (uintptr_t)®s) #define CODECACHE_SIZE (2 << 25) +#define CODECACHE_OVERHEAD (CODECACHE_SIZE - 1_kb) struct Dynarec { Dynarec(); ~Dynarec(); - int Step(Mem&, n64::Registers&); + int Step(Mem&); void Reset() { code.reset(); + regs.Reset(); InvalidateCache(); } u64 cop2Latch{}; CodeGenerator code; + n64::Registers regs; void InvalidatePage(u32); void InvalidateCache(); private: - friend struct Cop1; + friend struct n64::Cop1; Fn* blockCache[0x80000]{}; u8* codeCache; int instrInBlock = 0; bool enableBreakpoints = false; u64 sizeUsed = 0; + std::ofstream dump; inline void emitBreakpoint() { #ifndef NDEBUG @@ -40,11 +47,11 @@ private: } void* bumpAlloc(u64 size, u8 val = 0); - void Recompile(n64::Registers&, Mem&, u32 pc); + void Recompile(Mem&, u32 pc); void AllocateOuter(u32 pc); - void cop2Decode(n64::Registers&, u32); - bool special(n64::Registers&, u32); - bool regimm(n64::Registers&, u32); - bool Exec(n64::Registers&, Mem&, u32); + void cop2Decode(u32); + bool special(u32); + bool regimm(u32); + bool Exec(Mem&, u32); }; } diff --git a/src/backend/core/Interpreter.cpp b/src/backend/core/Interpreter.cpp index 968a8fd3..0b9df763 100644 --- a/src/backend/core/Interpreter.cpp +++ b/src/backend/core/Interpreter.cpp @@ -21,7 +21,7 @@ inline void CheckCompareInterrupt(MI& mi, Registers& regs) { } } -void Interpreter::Step(Mem& mem, Registers& regs) { +void Interpreter::Step(Mem& mem) { regs.gpr[0] = 0; CheckCompareInterrupt(mem.mmio.mi, regs); @@ -40,6 +40,6 @@ void Interpreter::Step(Mem& mem, Registers& regs) { regs.pc = regs.nextPC; regs.nextPC += 4; - Exec(regs, mem, instruction); + Exec(mem, instruction); } } \ No newline at end of file diff --git a/src/backend/core/Interpreter.hpp b/src/backend/core/Interpreter.hpp index 6dcd2de5..05cd0152 100644 --- a/src/backend/core/Interpreter.hpp +++ b/src/backend/core/Interpreter.hpp @@ -7,106 +7,110 @@ namespace n64 { struct Interpreter { Interpreter() = default; ~Interpreter() = default; - void Step(Mem&, Registers&); + void Step(Mem&); + void Reset() { + regs.Reset(); + } + Registers regs; private: u64 cop2Latch{}; friend struct Cop1; - void cop2Decode(Registers&, u32); - void special(Registers&, u32); - void regimm(Registers&, u32); - void Exec(Registers&, Mem&, u32); - void add(Registers&, u32); - void addu(Registers&, u32); - void addi(Registers&, u32); - void addiu(Registers&, u32); - void andi(Registers&, u32); - void and_(Registers&, u32); - void branch(Registers&, bool, s64); - void branch_likely(Registers&, bool, s64); - void b(Registers&, u32, bool); - void blink(Registers&, u32, bool); - void bl(Registers&, u32, bool); - void bllink(Registers&, u32, bool); - void dadd(Registers&, u32); - void daddu(Registers&, u32); - void daddi(Registers&, u32); - void daddiu(Registers&, u32); - void ddiv(Registers&, u32); - void ddivu(Registers&, u32); - void div(Registers&, u32); - void divu(Registers&, u32); - void dmult(Registers&, u32); - void dmultu(Registers&, u32); - void dsll(Registers&, u32); - void dsllv(Registers&, u32); - void dsll32(Registers&, u32); - void dsra(Registers&, u32); - void dsrav(Registers&, u32); - void dsra32(Registers&, u32); - void dsrl(Registers&, u32); - void dsrlv(Registers&, u32); - void dsrl32(Registers&, u32); - void dsub(Registers&, u32); - void dsubu(Registers&, u32); - void j(Registers&, u32); - void jr(Registers&, u32); - void jal(Registers&, u32); - void jalr(Registers&, u32); - void lui(Registers&, u32); - void lbu(Registers&, Mem&, u32); - void lb(Registers&, Mem&, u32); - void ld(Registers&, Mem&, u32); - void ldl(Registers&, Mem&, u32); - void ldr(Registers&, Mem&, u32); - void lh(Registers&, Mem&, u32); - void lhu(Registers&, Mem&, u32); - void ll(Registers&, Mem&, u32); - void lld(Registers&, Mem&, u32); - void lw(Registers&, Mem&, u32); - void lwl(Registers&, Mem&, u32); - void lwu(Registers&, Mem&, u32); - void lwr(Registers&, Mem&, u32); - void mfhi(Registers&, u32); - void mflo(Registers&, u32); - void mult(Registers&, u32); - void multu(Registers&, u32); - void mthi(Registers&, u32); - void mtlo(Registers&, u32); - void nor(Registers&, u32); - void sb(Registers&, Mem&, u32); - void sc(Registers&, Mem&, u32); - void scd(Registers&, Mem&, u32); - void sd(Registers&, Mem&, u32); - void sdl(Registers&, Mem&, u32); - void sdr(Registers&, Mem&, u32); - void sh(Registers&, Mem&, u32); - void sw(Registers&, Mem&, u32); - void swl(Registers&, Mem&, u32); - void swr(Registers&, Mem&, u32); - void slti(Registers&, u32); - void sltiu(Registers&, u32); - void slt(Registers&, u32); - void sltu(Registers&, u32); - void sll(Registers&, u32); - void sllv(Registers&, u32); - void sub(Registers&, u32); - void subu(Registers&, u32); - void sra(Registers&, u32); - void srav(Registers&, u32); - void srl(Registers&, u32); - void srlv(Registers&, u32); - void trap(Registers&, bool); - void or_(Registers&, u32); - void ori(Registers&, u32); - void xor_(Registers&, u32); - void xori(Registers&, u32); + void cop2Decode(u32); + void special(u32); + void regimm(u32); + void Exec(Mem&, u32); + void add(u32); + void addu(u32); + void addi(u32); + void addiu(u32); + void andi(u32); + void and_(u32); + void branch(bool, s64); + void branch_likely(bool, s64); + void b(u32, bool); + void blink(u32, bool); + void bl(u32, bool); + void bllink(u32, bool); + void dadd(u32); + void daddu(u32); + void daddi(u32); + void daddiu(u32); + void ddiv(u32); + void ddivu(u32); + void div(u32); + void divu(u32); + void dmult(u32); + void dmultu(u32); + void dsll(u32); + void dsllv(u32); + void dsll32(u32); + void dsra(u32); + void dsrav(u32); + void dsra32(u32); + void dsrl(u32); + void dsrlv(u32); + void dsrl32(u32); + void dsub(u32); + void dsubu(u32); + void j(u32); + void jr(u32); + void jal(u32); + void jalr(u32); + void lui(u32); + void lbu(Mem&, u32); + void lb(Mem&, u32); + void ld(Mem&, u32); + void ldl(Mem&, u32); + void ldr(Mem&, u32); + void lh(Mem&, u32); + void lhu(Mem&, u32); + void ll(Mem&, u32); + void lld(Mem&, u32); + void lw(Mem&, u32); + void lwl(Mem&, u32); + void lwu(Mem&, u32); + void lwr(Mem&, u32); + void mfhi(u32); + void mflo(u32); + void mult(u32); + void multu(u32); + void mthi(u32); + void mtlo(u32); + void nor(u32); + void sb(Mem&, u32); + void sc(Mem&, u32); + void scd(Mem&, u32); + void sd(Mem&, u32); + void sdl(Mem&, u32); + void sdr(Mem&, u32); + void sh(Mem&, u32); + void sw(Mem&, u32); + void swl(Mem&, u32); + void swr(Mem&, u32); + void slti(u32); + void sltiu(u32); + void slt(u32); + void sltu(u32); + void sll(u32); + void sllv(u32); + void sub(u32); + void subu(u32); + void sra(u32); + void srav(u32); + void srl(u32); + void srlv(u32); + void trap(bool); + void or_(u32); + void ori(u32); + void xor_(u32); + void xori(u32); - void mtc2(Registers&, u32); - void mfc2(Registers&, u32); - void dmtc2(Registers&, u32); - void dmfc2(Registers&, u32); - void ctc2(Registers&, u32); - void cfc2(Registers&, u32); + void mtc2(u32); + void mfc2(u32); + void dmtc2(u32); + void dmfc2(u32); + void ctc2(u32); + void cfc2(u32); }; } diff --git a/src/backend/core/RSP.hpp b/src/backend/core/RSP.hpp index 533f2492..c3afa2e1 100644 --- a/src/backend/core/RSP.hpp +++ b/src/backend/core/RSP.hpp @@ -281,6 +281,7 @@ struct RSP { void ssv(u32 instr); void suv(u32 instr); void slv(u32 instr); + void sfv(u32 instr); void spv(u32 instr); void sllv(u32 instr); void srlv(u32 instr); diff --git a/src/backend/core/dynarec/cop/cop0decode.cpp b/src/backend/core/dynarec/cop/cop0decode.cpp index 8dedc1a9..8fc359ac 100644 --- a/src/backend/core/dynarec/cop/cop0decode.cpp +++ b/src/backend/core/dynarec/cop/cop0decode.cpp @@ -21,7 +21,7 @@ void cop0Decode(n64::Registers& regs, u32 instr, Dynarec& cpu) { break; case 0x04: code.mov(code.rsi, (u64)instr); - code.mov(code.rax, (u64)mtc0); + code.mov(code.rax, (uintptr_t)mtc0); code.call(code.rax); break; case 0x05: diff --git a/src/backend/core/dynarec/cop/cop1instructions.cpp b/src/backend/core/dynarec/cop/cop1instructions.cpp index d3a4bf4e..4d93d82b 100644 --- a/src/backend/core/dynarec/cop/cop1instructions.cpp +++ b/src/backend/core/dynarec/cop/cop1instructions.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -19,65 +20,39 @@ inline int PushRoundingMode(const FCR31& fcr31) { #define PUSHROUNDINGMODE int og = PushRoundingMode(regs.cop1.fcr31) #define POPROUNDINGMODE fesetround(og) -#ifdef _WIN32 -#define isnanf isnan -#define checknanregsf(fs, ft) \ - if(isnanf(fs) || isnanf(ft)) { \ +#define checknanregs(fs, ft) do { \ + if(std::isnan(fs) || std::isnan(ft)) { \ regs.cop1.fcr31.flag_invalid_operation = true; \ regs.cop1.fcr31.cause_invalid_operation = true; \ FireException(regs, ExceptionCode::FloatingPointError, 1, true); \ return; \ - } - -#define checknanregsd(fs, ft) \ - if(isnan(fs) || isnan(ft)) { \ - regs.cop1.fcr31.flag_invalid_operation = true; \ - regs.cop1.fcr31.cause_invalid_operation = true; \ - FireException(regs, ExceptionCode::FloatingPointError, 1, true); \ - return; \ - } -#else -#define checknanregsf(fs, ft) \ - if(isnanf(fs) || isnanf(ft)) { \ - regs.cop1.fcr31.flag_invalid_operation = true; \ - regs.cop1.fcr31.cause_invalid_operation = true; \ - FireException(regs, ExceptionCode::FloatingPointError, 1, true); \ - return; \ - } - -#define checknanregsd(fs, ft) \ - if(isnan(fs) || isnan(ft)) { \ - regs.cop1.fcr31.flag_invalid_operation = true; \ - regs.cop1.fcr31.cause_invalid_operation = true; \ - FireException(regs, ExceptionCode::FloatingPointError, 1, true); \ - return; \ - } -#endif + } \ +} while(0) void absd(n64::Registers& regs, u32 instr) { double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), fabs(fs)); + regs.cop1.SetCop1Reg(regs.cop0, FD(instr), std::abs(fs)); } void abss(n64::Registers& regs, u32 instr) { float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), fabsf(fs)); + regs.cop1.SetCop1Reg(regs.cop0, FD(instr), std::abs(fs)); } void absw(n64::Registers& regs, u32 instr) { s32 fs = regs.cop1.GetReg(regs.cop0, FS(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), abs(fs)); + regs.cop1.SetReg(regs.cop0, FD(instr), std::abs(fs)); } void absl(n64::Registers& regs, u32 instr) { s64 fs = regs.cop1.GetReg(regs.cop0, FS(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), labs(fs)); + regs.cop1.SetReg(regs.cop0, FD(instr), std::abs(fs)); } void adds(n64::Registers& regs, u32 instr) { float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); float ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); - checknanregsf(fs, ft) + checknanregs(fs, ft); float result = fs + ft; regs.cop1.SetCop1Reg(regs.cop0, FD(instr), result); } @@ -85,32 +60,32 @@ void adds(n64::Registers& regs, u32 instr) { void addd(n64::Registers& regs, u32 instr) { double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); double ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); - checknanregsf(fs, ft) + checknanregs(fs, ft); double result = fs + ft; regs.cop1.SetCop1Reg(regs.cop0, FD(instr), result); } void ceills(n64::Registers& regs, u32 instr) { float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s64 result = ceilf(fs); + s64 result = std::ceil(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } void ceilws(n64::Registers& regs, u32 instr) { float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s32 result = ceilf(fs); + s32 result = std::ceil(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } void ceilld(n64::Registers& regs, u32 instr) { double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s64 result = ceil(fs); + s64 result = std::ceil(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } void ceilwd(n64::Registers& regs, u32 instr) { double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s32 result = ceil(fs); + s32 result = std::ceil(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } @@ -410,60 +385,60 @@ void negd(Registers ®s, u32 instr) { void sqrts(Registers ®s, u32 instr) { float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), sqrtf(fs)); + regs.cop1.SetCop1Reg(regs.cop0, FD(instr), std::sqrt(fs)); } void sqrtd(Registers ®s, u32 instr) { double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), sqrt(fs)); + regs.cop1.SetCop1Reg(regs.cop0, FD(instr), std::sqrt(fs)); } void roundls(n64::Registers& regs, u32 instr) { float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); PUSHROUNDINGMODE; - regs.cop1.SetReg(regs.cop0, FD(instr), (s32)nearbyintf(fs)); + regs.cop1.SetReg(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); POPROUNDINGMODE; } void roundld(n64::Registers& regs, u32 instr) { double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); PUSHROUNDINGMODE; - regs.cop1.SetReg(regs.cop0, FD(instr), (s64)nearbyint(fs)); + regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::nearbyint(fs)); POPROUNDINGMODE; } void roundws(n64::Registers& regs, u32 instr) { float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); PUSHROUNDINGMODE; - regs.cop1.SetReg(regs.cop0, FD(instr), (s32)nearbyintf(fs)); + regs.cop1.SetReg(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); POPROUNDINGMODE; } void roundwd(n64::Registers& regs, u32 instr) { double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); PUSHROUNDINGMODE; - regs.cop1.SetReg(regs.cop0, FD(instr), (s32)nearbyint(fs)); + regs.cop1.SetReg(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); POPROUNDINGMODE; } void floorls(n64::Registers& regs, u32 instr) { float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), (s64)floorf(fs)); + regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); } void floorld(n64::Registers& regs, u32 instr) { double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), (s64)floor(fs)); + regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); } void floorws(n64::Registers& regs, u32 instr) { float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), (s64)floorf(fs)); + regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); } void floorwd(n64::Registers& regs, u32 instr) { double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), (s64)floor(fs)); + regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); } void lwc1(n64::Registers& regs, Mem& mem, u32 instr) { @@ -550,25 +525,25 @@ void sdc1(n64::Registers& regs, Mem& mem, u32 instr) { void truncws(n64::Registers& regs, u32 instr) { float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s32 result = (s32)truncf(fs); + s32 result = (s32)std::trunc(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } void truncwd(n64::Registers& regs, u32 instr) { double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s32 result = (s32)trunc(fs); + s32 result = (s32)std::trunc(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } void truncls(n64::Registers& regs, u32 instr) { float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s64 result = (s64)truncf(fs); + s64 result = (s64)std::trunc(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } void truncld(n64::Registers& regs, u32 instr) { double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s64 result = (s64)trunc(fs); + s64 result = (s64)std::trunc(fs); regs.cop1.SetReg(regs.cop0, FD(instr), result); } diff --git a/src/backend/core/dynarec/decode.cpp b/src/backend/core/dynarec/decode.cpp index edc45f4c..4327aaea 100644 --- a/src/backend/core/dynarec/decode.cpp +++ b/src/backend/core/dynarec/decode.cpp @@ -4,10 +4,10 @@ #include namespace n64::JIT { -void Dynarec::cop2Decode(n64::Registers& regs, u32 instr) { +void Dynarec::cop2Decode(u32 instr) { code.mov(rdi, (u64)this); code.mov(rsi, (u64)®s); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); switch(RS(instr)) { case 0x00: @@ -32,7 +32,7 @@ void Dynarec::cop2Decode(n64::Registers& regs, u32 instr) { } } -bool Dynarec::special(n64::Registers& regs, u32 instr) { +bool Dynarec::special(u32 instr) { u8 mask = (instr & 0x3F); bool res = false; @@ -40,44 +40,44 @@ bool Dynarec::special(n64::Registers& regs, u32 instr) { switch (mask) { // TODO: named constants for clearer code case 0: if (instr != 0) { - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)sll); code.call(rax); } break; case 0x02: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)srl); code.call(rax); break; case 0x03: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)sra); code.call(rax); break; case 0x04: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)sllv); code.call(rax); break; case 0x06: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)srlv); code.call(rax); break; case 0x07: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)srav); code.call(rax); break; case 0x08: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)jr); code.call(rax); res = true; break; case 0x09: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)jalr); code.call(rax); res = true; @@ -86,147 +86,147 @@ bool Dynarec::special(n64::Registers& regs, u32 instr) { case 0x0D: Util::panic("[RECOMPILER] Unhandled break instruction {:016X}\n", (u64)regs.pc); case 0x0F: break; // SYNC case 0x10: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)mfhi); code.call(rax); break; case 0x11: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)mthi); code.call(rax); break; case 0x12: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)mflo); code.call(rax); break; case 0x13: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)mtlo); code.call(rax); break; case 0x14: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)dsllv); code.call(rax); break; case 0x16: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)dsrlv); code.call(rax); break; case 0x17: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)dsrav); code.call(rax); break; case 0x18: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)mult); code.call(rax); break; case 0x19: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)multu); code.call(rax); break; case 0x1A: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)div); code.call(rax); break; case 0x1B: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)divu); code.call(rax); break; case 0x1C: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)dmult); code.call(rax); break; case 0x1D: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)dmultu); code.call(rax); break; case 0x1E: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)ddiv); code.call(rax); break; case 0x1F: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)ddivu); code.call(rax); break; case 0x20: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)add); code.call(rax); break; case 0x21: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)addu); code.call(rax); break; case 0x22: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)sub); code.call(rax); break; case 0x23: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)subu); code.call(rax); break; case 0x24: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)and_); code.call(rax); break; case 0x25: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)or_); code.call(rax); break; case 0x26: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)xor_); code.call(rax); break; case 0x27: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)nor); code.call(rax); break; case 0x2A: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)slt); code.call(rax); break; case 0x2B: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)sltu); code.call(rax); break; case 0x2C: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)dadd); code.call(rax); break; case 0x2D: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)daddu); code.call(rax); break; case 0x2E: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)dsub); code.call(rax); break; case 0x2F: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)dsubu); code.call(rax); break; @@ -291,32 +291,32 @@ bool Dynarec::special(n64::Registers& regs, u32 instr) { res = true; break; case 0x38: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)dsll); code.call(rax); break; case 0x3A: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)dsrl); code.call(rax); break; case 0x3B: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)dsra); code.call(rax); break; case 0x3C: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)dsll32); code.call(rax); break; case 0x3E: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)dsrl32); code.call(rax); break; case 0x3F: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)dsra32); code.call(rax); break; @@ -327,12 +327,12 @@ bool Dynarec::special(n64::Registers& regs, u32 instr) { return res; } -bool Dynarec::regimm(n64::Registers& regs, u32 instr) { +bool Dynarec::regimm(u32 instr) { u8 mask = ((instr >> 16) & 0x1F); // 000r_rccc switch (mask) { // TODO: named constants for clearer code case 0x00: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.xor_(rdx, rdx); code.cmp(r8, 0); @@ -341,7 +341,7 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) { code.call(rax); break; case 0x01: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.xor_(rdx, rdx); code.cmp(r8, 0); @@ -350,7 +350,7 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) { code.call(rax); break; case 0x02: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.xor_(rdx, rdx); code.cmp(r8, 0); @@ -359,7 +359,7 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) { code.call(rax); break; case 0x03: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.xor_(rdx, rdx); code.cmp(r8, 0); @@ -416,7 +416,7 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) { code.call(rax); break; case 0x10: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]); code.xor_(rdx, rdx); code.cmp(rcx, 0); @@ -425,7 +425,7 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) { code.call(rax); break; case 0x11: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]); code.xor_(rdx, rdx); code.cmp(rcx, 0); @@ -434,7 +434,7 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) { code.call(rax); break; case 0x12: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]); code.xor_(rdx, rdx); code.cmp(rcx, 0); @@ -443,7 +443,7 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) { code.call(rax); break; case 0x13: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr))]); code.xor_(rdx, rdx); code.cmp(rcx, 0); @@ -458,28 +458,28 @@ bool Dynarec::regimm(n64::Registers& regs, u32 instr) { return true; } -bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { +bool Dynarec::Exec(Mem& mem, u32 instr) { u8 mask = (instr >> 26) & 0x3f; bool res = false; // 00rr_rccc switch(mask) { // TODO: named constants for clearer code - case 0x00: res = special(regs, instr); break; - case 0x01: res = regimm(regs, instr); break; + case 0x00: res = special(instr); break; + case 0x01: res = regimm(instr); break; case 0x02: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)j); code.call(rax); res = true; break; case 0x03: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)jal); code.call(rax); res = true; break; case 0x04: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); code.xor_(rdx, rdx); @@ -490,7 +490,7 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { res = true; break; case 0x05: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); code.xor_(rdx, rdx); @@ -501,7 +501,7 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { res = true; break; case 0x06: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.xor_(rdx, rdx); code.test(r8, r8); @@ -511,7 +511,7 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { res = true; break; case 0x07: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.xor_(rdx, rdx); code.test(r8, r8); @@ -521,51 +521,50 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { res = true; break; case 0x08: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)addi); code.call(rax); break; case 0x09: - emitBreakpoint(); - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)addiu); code.call(rax); break; case 0x0A: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)slti); code.call(rax); break; case 0x0B: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)sltiu); code.call(rax); break; case 0x0C: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)andi); code.call(rax); break; case 0x0D: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)ori); code.call(rax); break; case 0x0E: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)xori); code.call(rax); break; case 0x0F: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)lui); code.call(rax); break; case 0x10: cop0Decode(regs, instr, *this); break; case 0x11: res = cop1Decode(regs, instr, *this); break; - case 0x12: cop2Decode(regs, instr); break; + case 0x12: cop2Decode(instr); break; case 0x14: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); code.xor_(rdx, rdx); @@ -575,7 +574,7 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { code.call(rax); break; case 0x15: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr))]); code.xor_(rdx, rdx); @@ -585,7 +584,7 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { code.call(rax); break; case 0x16: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.xor_(rdx, rdx); code.cmp(r8, 0); @@ -594,7 +593,7 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { code.call(rax); break; case 0x17: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr))]); code.xor_(rdx, rdx); code.cmp(r8, 0); @@ -603,186 +602,186 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { code.call(rax); break; case 0x18: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)daddi); code.call(rax); break; case 0x19: - code.mov(rsi, (u64)instr); + code.mov(rsi, instr); code.mov(rax, (u64)daddiu); code.call(rax); break; case 0x1A: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)ldl); code.call(rax); break; case 0x1B: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)ldr); code.call(rax); break; case 0x1F: Util::panic("[RECOMPILER] Unhandled reserved instruction exception {:016X}\n", regs.oldPC); break; case 0x20: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)lb); code.call(rax); break; case 0x21: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)lh); code.call(rax); break; case 0x22: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)lwl); code.call(rax); break; case 0x23: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)lw); code.call(rax); break; case 0x24: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)lbu); code.call(rax); break; case 0x25: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)lhu); code.call(rax); break; case 0x26: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)lwr); code.call(rax); break; case 0x27: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)lwu); code.call(rax); break; case 0x28: code.mov(rsi, (u64)&mem); code.mov(rdx, (u64)this); - code.mov(rcx, (u64)instr); + code.mov(rcx, instr); code.mov(rax, (u64)sb); code.call(rax); break; case 0x29: code.mov(rsi, (u64)&mem); code.mov(rdx, (u64)this); - code.mov(rcx, (u64)instr); + code.mov(rcx, instr); code.mov(rax, (u64)sh); code.call(rax); break; case 0x2A: code.mov(rsi, (u64)&mem); code.mov(rdx, (u64)this); - code.mov(rcx, (u64)instr); + code.mov(rcx, instr); code.mov(rax, (u64)swl); code.call(rax); break; case 0x2B: code.mov(rsi, (u64)&mem); code.mov(rdx, (u64)this); - code.mov(rcx, (u64)instr); + code.mov(rcx, instr); code.mov(rax, (u64)sw); code.call(rax); break; case 0x2C: code.mov(rsi, (u64)&mem); code.mov(rdx, (u64)this); - code.mov(rcx, (u64)instr); + code.mov(rcx, instr); code.mov(rax, (u64)sdl); code.call(rax); break; case 0x2D: code.mov(rsi, (u64)&mem); code.mov(rdx, (u64)this); - code.mov(rcx, (u64)instr); + code.mov(rcx, instr); code.mov(rax, (u64)sdr); code.call(rax); break; case 0x2E: code.mov(rsi, (u64)&mem); code.mov(rdx, (u64)this); - code.mov(rcx, (u64)instr); + code.mov(rcx, instr); code.mov(rax, (u64)swr); code.call(rax); break; case 0x2F: break; // CACHE case 0x30: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)ll); code.call(rax); break; case 0x31: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)lwc1); code.call(rax); break; case 0x34: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)lld); code.call(rax); break; case 0x35: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)ldc1); code.call(rax); break; case 0x37: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)ld); code.call(rax); break; case 0x38: code.mov(rsi, (u64)&mem); code.mov(rdx, (u64)this); - code.mov(rcx, (u64)instr); + code.mov(rcx, instr); code.mov(rax, (u64)sc); code.call(rax); break; case 0x39: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)swc1); code.call(rax); break; case 0x3C: code.mov(rsi, (u64)&mem); code.mov(rdx, (u64)this); - code.mov(rcx, (u64)instr); + code.mov(rcx, instr); code.mov(rax, (u64)scd); code.call(rax); break; case 0x3D: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, instr); code.mov(rax, (u64)sdc1); code.call(rax); break; case 0x3F: code.mov(rsi, (u64)&mem); code.mov(rdx, (u64)this); - code.mov(rcx, (u64)instr); + code.mov(rcx, instr); code.mov(rax, (u64)sd); code.call(rax); break; diff --git a/src/backend/core/dynarec/instructions.cpp b/src/backend/core/dynarec/instructions.cpp index c3766f28..9e838c15 100644 --- a/src/backend/core/dynarec/instructions.cpp +++ b/src/backend/core/dynarec/instructions.cpp @@ -41,6 +41,7 @@ void addiu(Registers& regs, u32 instr) { s16 imm = (s16)(instr); s32 result = rs + imm; regs.gpr[RT(instr)] = result; + Util::print("addiu {:08X}, {:04X} = {:08X} [reg: {:016X}]\n", (u32)rs, imm, (u32)result, (u64)regs.gpr[RT(instr)]); } void dadd(Registers& regs, u32 instr) { @@ -146,6 +147,7 @@ void ddivu(Registers& regs, u32 instr) { } void branch(Registers& regs, bool cond, s64 address) { + //Util::debug("\t\tJIT branch from {:08X} -> {:08X}\n", (u32)regs.oldPC, (u32)address); regs.delaySlot = true; if (cond) { regs.nextPC = address; @@ -155,8 +157,10 @@ void branch(Registers& regs, bool cond, s64 address) { void branch_likely(Registers& regs, bool cond, s64 address) { regs.delaySlot = true; if (cond) { + //Util::debug("\t\tJIT branch likely taken from {:08X} -> {:08X}\n", (u32)regs.oldPC, (u32)address); regs.nextPC = address; } else { + //Util::debug("\t\tJIT branch likely not taken from {:08X} -> {:08X}\n", (u32)regs.oldPC, (u32)address); regs.SetPC(regs.nextPC); } } diff --git a/src/backend/core/interpreter/cop/cop1instructions.cpp b/src/backend/core/interpreter/cop/cop1instructions.cpp index 11c0064d..c5cc1096 100644 --- a/src/backend/core/interpreter/cop/cop1instructions.cpp +++ b/src/backend/core/interpreter/cop/cop1instructions.cpp @@ -20,65 +20,39 @@ inline int PushRoundingMode(const FCR31& fcr31) { #define PUSHROUNDINGMODE int og = PushRoundingMode(fcr31) #define POPROUNDINGMODE fesetround(og) -#ifdef _WIN32 -#define isnanf isnan -#define checknanregsf(fs, ft) \ - if(isnanf(fs) || isnanf(ft)) { \ +#define checknanregs(fs, ft) do { \ + if(std::isnan(fs) || std::isnan(ft)) { \ regs.cop1.fcr31.flag_invalid_operation = true; \ regs.cop1.fcr31.cause_invalid_operation = true; \ FireException(regs, ExceptionCode::FloatingPointError, 1, true); \ return; \ - } - -#define checknanregsd(fs, ft) \ - if(isnan(fs) || isnan(ft)) { \ - regs.cop1.fcr31.flag_invalid_operation = true; \ - regs.cop1.fcr31.cause_invalid_operation = true; \ - FireException(regs, ExceptionCode::FloatingPointError, 1, true); \ - return; \ - } -#else -#define checknanregsf(fs, ft) \ - if(isnanf(fs) || isnanf(ft)) { \ - regs.cop1.fcr31.flag_invalid_operation = true; \ - regs.cop1.fcr31.cause_invalid_operation = true; \ - FireException(regs, ExceptionCode::FloatingPointError, 1, true); \ - return; \ - } - -#define checknanregsd(fs, ft) \ - if(isnan(fs) || isnan(ft)) { \ - regs.cop1.fcr31.flag_invalid_operation = true; \ - regs.cop1.fcr31.cause_invalid_operation = true; \ - FireException(regs, ExceptionCode::FloatingPointError, 1, true); \ - return; \ - } -#endif + } \ +} while(0) void Cop1::absd(Registers& regs, u32 instr) { double fs = GetCop1Reg(regs.cop0, FS(instr)); - SetCop1Reg(regs.cop0, FD(instr), fabs(fs)); + SetCop1Reg(regs.cop0, FD(instr), std::abs(fs)); } void Cop1::abss(Registers& regs, u32 instr) { float fs = GetCop1Reg(regs.cop0, FS(instr)); - SetCop1Reg(regs.cop0, FD(instr), fabsf(fs)); + SetCop1Reg(regs.cop0, FD(instr), std::abs(fs)); } void Cop1::absw(Registers& regs, u32 instr) { s32 fs = GetReg(regs.cop0, FS(instr)); - SetReg(regs.cop0, FD(instr), abs(fs)); + SetReg(regs.cop0, FD(instr), std::abs(fs)); } void Cop1::absl(Registers& regs, u32 instr) { s64 fs = GetReg(regs.cop0, FS(instr)); - SetReg(regs.cop0, FD(instr), labs(fs)); + SetReg(regs.cop0, FD(instr), std::abs(fs)); } void Cop1::adds(Registers& regs, u32 instr) { float fs = GetCop1Reg(regs.cop0, FS(instr)); float ft = GetCop1Reg(regs.cop0, FT(instr)); - checknanregsf(fs, ft) + checknanregs(fs, ft); float result = fs + ft; SetCop1Reg(regs.cop0, FD(instr), result); } @@ -86,32 +60,32 @@ void Cop1::adds(Registers& regs, u32 instr) { void Cop1::addd(Registers& regs, u32 instr) { double fs = GetCop1Reg(regs.cop0, FS(instr)); double ft = GetCop1Reg(regs.cop0, FT(instr)); - checknanregsf(fs, ft) + checknanregs(fs, ft); double result = fs + ft; SetCop1Reg(regs.cop0, FD(instr), result); } void Cop1::ceills(Registers& regs, u32 instr) { float fs = GetCop1Reg(regs.cop0, FS(instr)); - s64 result = ceilf(fs); + s64 result = std::ceil(fs); SetReg(regs.cop0, FD(instr), result); } void Cop1::ceilws(Registers& regs, u32 instr) { float fs = GetCop1Reg(regs.cop0, FS(instr)); - s32 result = ceilf(fs); + s32 result = std::ceil(fs); SetReg(regs.cop0, FD(instr), result); } void Cop1::ceilld(Registers& regs, u32 instr) { double fs = GetCop1Reg(regs.cop0, FS(instr)); - s64 result = ceil(fs); + s64 result = std::ceil(fs); SetReg(regs.cop0, FD(instr), result); } void Cop1::ceilwd(Registers& regs, u32 instr) { double fs = GetCop1Reg(regs.cop0, FS(instr)); - s32 result = ceil(fs); + s32 result = std::ceil(fs); SetReg(regs.cop0, FD(instr), result); } @@ -411,60 +385,60 @@ void Cop1::negd(Registers ®s, u32 instr) { void Cop1::sqrts(Registers ®s, u32 instr) { float fs = GetCop1Reg(regs.cop0, FS(instr)); - SetCop1Reg(regs.cop0, FD(instr), sqrtf(fs)); + SetCop1Reg(regs.cop0, FD(instr), std::sqrt(fs)); } void Cop1::sqrtd(Registers ®s, u32 instr) { double fs = GetCop1Reg(regs.cop0, FS(instr)); - SetCop1Reg(regs.cop0, FD(instr), sqrt(fs)); + SetCop1Reg(regs.cop0, FD(instr), std::sqrt(fs)); } void Cop1::roundls(Registers& regs, u32 instr) { float fs = GetCop1Reg(regs.cop0, FS(instr)); PUSHROUNDINGMODE; - SetReg(regs.cop0, FD(instr), (s32)nearbyintf(fs)); + SetReg(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); POPROUNDINGMODE; } void Cop1::roundld(Registers& regs, u32 instr) { double fs = GetCop1Reg(regs.cop0, FS(instr)); PUSHROUNDINGMODE; - SetReg(regs.cop0, FD(instr), (s64)nearbyint(fs)); + SetReg(regs.cop0, FD(instr), (s64)std::nearbyint(fs)); POPROUNDINGMODE; } void Cop1::roundws(Registers& regs, u32 instr) { float fs = GetCop1Reg(regs.cop0, FS(instr)); PUSHROUNDINGMODE; - SetReg(regs.cop0, FD(instr), (s32)nearbyintf(fs)); + SetReg(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); POPROUNDINGMODE; } void Cop1::roundwd(Registers& regs, u32 instr) { double fs = GetCop1Reg(regs.cop0, FS(instr)); PUSHROUNDINGMODE; - SetReg(regs.cop0, FD(instr), (s32)nearbyint(fs)); + SetReg(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); POPROUNDINGMODE; } void Cop1::floorls(Registers& regs, u32 instr) { float fs = GetCop1Reg(regs.cop0, FS(instr)); - SetReg(regs.cop0, FD(instr), (s64)floorf(fs)); + SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); } void Cop1::floorld(Registers& regs, u32 instr) { double fs = GetCop1Reg(regs.cop0, FS(instr)); - SetReg(regs.cop0, FD(instr), (s64)floor(fs)); + SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); } void Cop1::floorws(Registers& regs, u32 instr) { float fs = GetCop1Reg(regs.cop0, FS(instr)); - SetReg(regs.cop0, FD(instr), (s64)floorf(fs)); + SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); } void Cop1::floorwd(Registers& regs, u32 instr) { double fs = GetCop1Reg(regs.cop0, FS(instr)); - SetReg(regs.cop0, FD(instr), (s64)floor(fs)); + SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); } void Cop1::lwc1(Registers& regs, Mem& mem, u32 instr) { @@ -551,25 +525,25 @@ void Cop1::sdc1(Registers& regs, Mem& mem, u32 instr) { void Cop1::truncws(Registers& regs, u32 instr) { float fs = GetCop1Reg(regs.cop0, FS(instr)); - s32 result = (s32)truncf(fs); + s32 result = (s32)std::trunc(fs); SetReg(regs.cop0, FD(instr), result); } void Cop1::truncwd(Registers& regs, u32 instr) { double fs = GetCop1Reg(regs.cop0, FS(instr)); - s32 result = (s32)trunc(fs); + s32 result = (s32)std::trunc(fs); SetReg(regs.cop0, FD(instr), result); } void Cop1::truncls(Registers& regs, u32 instr) { float fs = GetCop1Reg(regs.cop0, FS(instr)); - s64 result = (s64)truncf(fs); + s64 result = (s64)std::trunc(fs); SetReg(regs.cop0, FD(instr), result); } void Cop1::truncld(Registers& regs, u32 instr) { double fs = GetCop1Reg(regs.cop0, FS(instr)); - s64 result = (s64)trunc(fs); + s64 result = (s64)std::trunc(fs); SetReg(regs.cop0, FD(instr), result); } diff --git a/src/backend/core/interpreter/decode.cpp b/src/backend/core/interpreter/decode.cpp index 9012f5e1..08a3cf8b 100644 --- a/src/backend/core/interpreter/decode.cpp +++ b/src/backend/core/interpreter/decode.cpp @@ -2,172 +2,172 @@ #include namespace n64 { -void Interpreter::special(Registers& regs, u32 instr) { +void Interpreter::special(u32 instr) { u8 mask = (instr & 0x3F); // 00rr_rccc switch (mask) { // TODO: named constants for clearer code case 0: if (instr != 0) { - sll(regs, instr); + sll(instr); } break; - case 0x02: srl(regs, instr); break; - case 0x03: sra(regs, instr); break; - case 0x04: sllv(regs, instr); break; - case 0x06: srlv(regs, instr); break; - case 0x07: srav(regs, instr); break; - case 0x08: jr(regs, instr); break; - case 0x09: jalr(regs, instr); break; + case 0x02: srl(instr); break; + case 0x03: sra(instr); break; + case 0x04: sllv(instr); break; + case 0x06: srlv(instr); break; + case 0x07: srav(instr); break; + case 0x08: jr(instr); break; + case 0x09: jalr(instr); break; case 0x0C: FireException(regs, ExceptionCode::Syscall, 0, true); break; case 0x0D: FireException(regs, ExceptionCode::Breakpoint, 0, true); break; case 0x0F: break; // SYNC - case 0x10: mfhi(regs, instr); break; - case 0x11: mthi(regs, instr); break; - case 0x12: mflo(regs, instr); break; - case 0x13: mtlo(regs, instr); break; - case 0x14: dsllv(regs, instr); break; - case 0x16: dsrlv(regs, instr); break; - case 0x17: dsrav(regs, instr); break; - case 0x18: mult(regs, instr); break; - case 0x19: multu(regs, instr); break; - case 0x1A: div(regs, instr); break; - case 0x1B: divu(regs, instr); break; - case 0x1C: dmult(regs, instr); break; - case 0x1D: dmultu(regs, instr); break; - case 0x1E: ddiv(regs, instr); break; - case 0x1F: ddivu(regs, instr); break; - case 0x20: add(regs, instr); break; - case 0x21: addu(regs, instr); break; - case 0x22: sub(regs, instr); break; - case 0x23: subu(regs, instr); break; - case 0x24: and_(regs, instr); break; - case 0x25: or_(regs, instr); break; - case 0x26: xor_(regs, instr); break; - case 0x27: nor(regs, instr); break; - case 0x2A: slt(regs, instr); break; - case 0x2B: sltu(regs, instr); break; - case 0x2C: dadd(regs, instr); break; - case 0x2D: daddu(regs, instr); break; - case 0x2E: dsub(regs, instr); break; - case 0x2F: dsubu(regs, instr); break; - case 0x30: trap(regs, regs.gpr[RS(instr)] >= regs.gpr[RT(instr)]); break; - case 0x31: trap(regs, (u64)regs.gpr[RS(instr)] >= (u64)regs.gpr[RT(instr)]); break; - case 0x32: trap(regs, regs.gpr[RS(instr)] < regs.gpr[RT(instr)]); break; - case 0x33: trap(regs, (u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]); break; - case 0x34: trap(regs, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; - case 0x36: trap(regs, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break; - case 0x38: dsll(regs, instr); break; - case 0x3A: dsrl(regs, instr); break; - case 0x3B: dsra(regs, instr); break; - case 0x3C: dsll32(regs, instr); break; - case 0x3E: dsrl32(regs, instr); break; - case 0x3F: dsra32(regs, instr); break; + case 0x10: mfhi(instr); break; + case 0x11: mthi(instr); break; + case 0x12: mflo(instr); break; + case 0x13: mtlo(instr); break; + case 0x14: dsllv(instr); break; + case 0x16: dsrlv(instr); break; + case 0x17: dsrav(instr); break; + case 0x18: mult(instr); break; + case 0x19: multu(instr); break; + case 0x1A: div(instr); break; + case 0x1B: divu(instr); break; + case 0x1C: dmult(instr); break; + case 0x1D: dmultu(instr); break; + case 0x1E: ddiv(instr); break; + case 0x1F: ddivu(instr); break; + case 0x20: add(instr); break; + case 0x21: addu(instr); break; + case 0x22: sub(instr); break; + case 0x23: subu(instr); break; + case 0x24: and_(instr); break; + case 0x25: or_(instr); break; + case 0x26: xor_(instr); break; + case 0x27: nor(instr); break; + case 0x2A: slt(instr); break; + case 0x2B: sltu(instr); break; + case 0x2C: dadd(instr); break; + case 0x2D: daddu(instr); break; + case 0x2E: dsub(instr); break; + case 0x2F: dsubu(instr); break; + case 0x30: trap(regs.gpr[RS(instr)] >= regs.gpr[RT(instr)]); break; + case 0x31: trap((u64)regs.gpr[RS(instr)] >= (u64)regs.gpr[RT(instr)]); break; + case 0x32: trap(regs.gpr[RS(instr)] < regs.gpr[RT(instr)]); break; + case 0x33: trap((u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]); break; + case 0x34: trap(regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; + case 0x36: trap(regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break; + case 0x38: dsll(instr); break; + case 0x3A: dsrl(instr); break; + case 0x3B: dsra(instr); break; + case 0x3C: dsll32(instr); break; + case 0x3E: dsrl32(instr); break; + case 0x3F: dsra32(instr); break; default: Util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 7, mask & 7, instr, (u64)regs.oldPC); } } -void Interpreter::regimm(Registers& regs, u32 instr) { +void Interpreter::regimm(u32 instr) { u8 mask = ((instr >> 16) & 0x1F); // 000r_rccc switch (mask) { // TODO: named constants for clearer code - case 0x00: b(regs, instr, regs.gpr[RS(instr)] < 0); break; - case 0x01: b(regs, instr, regs.gpr[RS(instr)] >= 0); break; - case 0x02: bl(regs, instr, regs.gpr[RS(instr)] < 0); break; - case 0x03: bl(regs, instr, regs.gpr[RS(instr)] >= 0); break; - case 0x08: trap(regs, regs.gpr[RS(instr)] >= s64(s16(instr))); break; - case 0x09: trap(regs, u64(regs.gpr[RS(instr)]) >= u64(s64(s16(instr)))); break; - case 0x0A: trap(regs, regs.gpr[RS(instr)] < s64(s16(instr))); break; - case 0x0B: trap(regs, u64(regs.gpr[RS(instr)]) < u64(s64(s16(instr)))); break; - case 0x0C: trap(regs, regs.gpr[RS(instr)] == s64(s16(instr))); break; - case 0x0E: trap(regs, regs.gpr[RS(instr)] != s64(s16(instr))); break; - case 0x10: blink(regs, instr, regs.gpr[RS(instr)] < 0); break; - case 0x11: blink(regs, instr, regs.gpr[RS(instr)] >= 0); break; - case 0x12: bllink(regs, instr, regs.gpr[RS(instr)] < 0); break; - case 0x13: bllink(regs, instr, regs.gpr[RS(instr)] >= 0); break; + case 0x00: b(instr, regs.gpr[RS(instr)] < 0); break; + case 0x01: b(instr, regs.gpr[RS(instr)] >= 0); break; + case 0x02: bl(instr, regs.gpr[RS(instr)] < 0); break; + case 0x03: bl(instr, regs.gpr[RS(instr)] >= 0); break; + case 0x08: trap(regs.gpr[RS(instr)] >= s64(s16(instr))); break; + case 0x09: trap(u64(regs.gpr[RS(instr)]) >= u64(s64(s16(instr)))); break; + case 0x0A: trap(regs.gpr[RS(instr)] < s64(s16(instr))); break; + case 0x0B: trap(u64(regs.gpr[RS(instr)]) < u64(s64(s16(instr)))); break; + case 0x0C: trap(regs.gpr[RS(instr)] == s64(s16(instr))); break; + case 0x0E: trap(regs.gpr[RS(instr)] != s64(s16(instr))); break; + case 0x10: blink(instr, regs.gpr[RS(instr)] < 0); break; + case 0x11: blink(instr, regs.gpr[RS(instr)] >= 0); break; + case 0x12: bllink(instr, regs.gpr[RS(instr)] < 0); break; + case 0x13: bllink(instr, regs.gpr[RS(instr)] >= 0); break; default: Util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC); } } -void Interpreter::cop2Decode(Registers& regs, u32 instr) { +void Interpreter::cop2Decode(u32 instr) { if(!regs.cop0.status.cu2) { FireException(regs, ExceptionCode::CoprocessorUnusable, 2, true); return; } switch(RS(instr)) { - case 0x00: mfc2(regs, instr); break; - case 0x01: dmfc2(regs, instr); break; - case 0x02: cfc2(regs, instr); break; - case 0x04: mtc2(regs, instr); break; - case 0x05: dmtc2(regs, instr); break; - case 0x06: ctc2(regs, instr); break; + case 0x00: mfc2(instr); break; + case 0x01: dmfc2(instr); break; + case 0x02: cfc2(instr); break; + case 0x04: mtc2(instr); break; + case 0x05: dmtc2(instr); break; + case 0x06: ctc2(instr); break; default: FireException(regs, ExceptionCode::ReservedInstruction, 2, true); } } -void Interpreter::Exec(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::Exec(Mem& mem, u32 instr) { u8 mask = (instr >> 26) & 0x3f; // 00rr_rccc switch(mask) { // TODO: named constants for clearer code - case 0x00: special(regs, instr); break; - case 0x01: regimm(regs, instr); break; - case 0x02: j(regs, instr); break; - case 0x03: jal(regs, instr); break; - case 0x04: b(regs, instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; + case 0x00: special(instr); break; + case 0x01: regimm(instr); break; + case 0x02: j(instr); break; + case 0x03: jal(instr); break; + case 0x04: b(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; case 0x05: { //fmt::print("RS: {:016X}, RT: {:016X}\n", (u64)regs.gpr[RS(instr)], (u64)regs.gpr[RT(instr)]); - b(regs, instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); + b(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); } break; - case 0x06: b(regs, instr, regs.gpr[RS(instr)] <= 0); break; - case 0x07: b(regs, instr, regs.gpr[RS(instr)] > 0); break; - case 0x08: addi(regs, instr); break; - case 0x09: addiu(regs, instr); break; - case 0x0A: slti(regs, instr); break; - case 0x0B: sltiu(regs, instr); break; - case 0x0C: andi(regs, instr); break; - case 0x0D: ori(regs, instr); break; - case 0x0E: xori(regs, instr); break; - case 0x0F: lui(regs, instr); break; + case 0x06: b(instr, regs.gpr[RS(instr)] <= 0); break; + case 0x07: b(instr, regs.gpr[RS(instr)] > 0); break; + case 0x08: addi(instr); break; + case 0x09: addiu(instr); break; + case 0x0A: slti(instr); break; + case 0x0B: sltiu(instr); break; + case 0x0C: andi(instr); break; + case 0x0D: ori(instr); break; + case 0x0E: xori(instr); break; + case 0x0F: lui(instr); break; case 0x10: regs.cop0.decode(regs, mem, instr); break; case 0x11: regs.cop1.decode(regs, *this, instr); break; - case 0x12: cop2Decode(regs, instr); break; - case 0x14: bl(regs, instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; - case 0x15: bl(regs, instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break; - case 0x16: bl(regs, instr, regs.gpr[RS(instr)] <= 0); break; - case 0x17: bl(regs, instr, regs.gpr[RS(instr)] > 0); break; - case 0x18: daddi(regs, instr); break; - case 0x19: daddiu(regs, instr); break; - case 0x1A: ldl(regs, mem, instr); break; - case 0x1B: ldr(regs, mem, instr); break; + case 0x12: cop2Decode(instr); break; + case 0x14: bl(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break; + case 0x15: bl(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break; + case 0x16: bl(instr, regs.gpr[RS(instr)] <= 0); break; + case 0x17: bl(instr, regs.gpr[RS(instr)] > 0); break; + case 0x18: daddi(instr); break; + case 0x19: daddiu(instr); break; + case 0x1A: ldl(mem, instr); break; + case 0x1B: ldr(mem, instr); break; case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, true); break; - case 0x20: lb(regs, mem, instr); break; - case 0x21: lh(regs, mem, instr); break; - case 0x22: lwl(regs, mem, instr); break; - case 0x23: lw(regs, mem, instr); break; - case 0x24: lbu(regs, mem, instr); break; - case 0x25: lhu(regs, mem, instr); break; - case 0x26: lwr(regs, mem, instr); break; - case 0x27: lwu(regs, mem, instr); break; - case 0x28: sb(regs, mem, instr); break; - case 0x29: sh(regs, mem, instr); break; - case 0x2A: swl(regs, mem, instr); break; - case 0x2B: sw(regs, mem, instr); break; - case 0x2C: sdl(regs, mem, instr); break; - case 0x2D: sdr(regs, mem, instr); break; - case 0x2E: swr(regs, mem, instr); break; + case 0x20: lb(mem, instr); break; + case 0x21: lh(mem, instr); break; + case 0x22: lwl(mem, instr); break; + case 0x23: lw(mem, instr); break; + case 0x24: lbu(mem, instr); break; + case 0x25: lhu(mem, instr); break; + case 0x26: lwr(mem, instr); break; + case 0x27: lwu(mem, instr); break; + case 0x28: sb(mem, instr); break; + case 0x29: sh(mem, instr); break; + case 0x2A: swl(mem, instr); break; + case 0x2B: sw(mem, instr); break; + case 0x2C: sdl(mem, instr); break; + case 0x2D: sdr(mem, instr); break; + case 0x2E: swr(mem, instr); break; case 0x2F: break; // CACHE - case 0x30: ll(regs, mem, instr); break; + case 0x30: ll(mem, instr); break; case 0x31: regs.cop1.lwc1(regs, mem, instr); break; - case 0x34: lld(regs, mem, instr); break; + case 0x34: lld(mem, instr); break; case 0x35: regs.cop1.ldc1(regs, mem, instr); break; - case 0x37: ld(regs, mem, instr); break; - case 0x38: sc(regs, mem, instr); break; + case 0x37: ld(mem, instr); break; + case 0x38: sc(mem, instr); break; case 0x39: regs.cop1.swc1(regs, mem, instr); break; - case 0x3C: scd(regs, mem, instr); break; + case 0x3C: scd(mem, instr); break; case 0x3D: regs.cop1.sdc1(regs, mem, instr); break; - case 0x3F: sd(regs, mem, instr); break; + case 0x3F: sd(mem, instr); break; default: Util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})\n", mask, instr, (u64)regs.oldPC); } diff --git a/src/backend/core/interpreter/instructions.cpp b/src/backend/core/interpreter/instructions.cpp index 877b6553..cb24a4cf 100644 --- a/src/backend/core/interpreter/instructions.cpp +++ b/src/backend/core/interpreter/instructions.cpp @@ -6,7 +6,7 @@ #define check_signed_underflow(op1, op2, res) (((((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1) namespace n64 { -void Interpreter::add(Registers& regs, u32 instr) { +void Interpreter::add(u32 instr) { u32 rs = (s32)regs.gpr[RS(instr)]; u32 rt = (s32)regs.gpr[RT(instr)]; u32 result = rs + rt; @@ -17,14 +17,14 @@ void Interpreter::add(Registers& regs, u32 instr) { } } -void Interpreter::addu(Registers& regs, u32 instr) { +void Interpreter::addu(u32 instr) { s32 rs = (s32)regs.gpr[RS(instr)]; s32 rt = (s32)regs.gpr[RT(instr)]; s32 result = rs + rt; regs.gpr[RD(instr)] = result; } -void Interpreter::addi(Registers& regs, u32 instr) { +void Interpreter::addi(u32 instr) { u32 rs = regs.gpr[RS(instr)]; u32 imm = s32(s16(instr)); u32 result = rs + imm; @@ -35,14 +35,14 @@ void Interpreter::addi(Registers& regs, u32 instr) { } } -void Interpreter::addiu(Registers& regs, u32 instr) { +void Interpreter::addiu(u32 instr) { s32 rs = (s32)regs.gpr[RS(instr)]; s16 imm = (s16)(instr); s32 result = rs + imm; regs.gpr[RT(instr)] = result; } -void Interpreter::dadd(Registers& regs, u32 instr) { +void Interpreter::dadd(u32 instr) { u64 rs = regs.gpr[RS(instr)]; u64 rt = regs.gpr[RT(instr)]; u64 result = rt + rs; @@ -53,13 +53,13 @@ void Interpreter::dadd(Registers& regs, u32 instr) { } } -void Interpreter::daddu(Registers& regs, u32 instr) { +void Interpreter::daddu(u32 instr) { s64 rs = regs.gpr[RS(instr)]; s64 rt = regs.gpr[RT(instr)]; regs.gpr[RD(instr)] = rs + rt; } -void Interpreter::daddi(Registers& regs, u32 instr) { +void Interpreter::daddi(u32 instr) { u64 imm = s64(s16(instr)); u64 rs = regs.gpr[RS(instr)]; u64 result = imm + rs; @@ -70,13 +70,13 @@ void Interpreter::daddi(Registers& regs, u32 instr) { } } -void Interpreter::daddiu(Registers& regs, u32 instr) { +void Interpreter::daddiu(u32 instr) { s16 imm = (s16)(instr); s64 rs = regs.gpr[RS(instr)]; regs.gpr[RT(instr)] = rs + imm; } -void Interpreter::div(Registers& regs, u32 instr) { +void Interpreter::div(u32 instr) { s64 dividend = (s32)regs.gpr[RS(instr)]; s64 divisor = (s32)regs.gpr[RT(instr)]; @@ -95,7 +95,7 @@ void Interpreter::div(Registers& regs, u32 instr) { } } -void Interpreter::divu(Registers& regs, u32 instr) { +void Interpreter::divu(u32 instr) { u32 dividend = regs.gpr[RS(instr)]; u32 divisor = regs.gpr[RT(instr)]; if(divisor == 0) { @@ -109,7 +109,7 @@ void Interpreter::divu(Registers& regs, u32 instr) { } } -void Interpreter::ddiv(Registers& regs, u32 instr) { +void Interpreter::ddiv(u32 instr) { s64 dividend = regs.gpr[RS(instr)]; s64 divisor = regs.gpr[RT(instr)]; if (dividend == 0x8000000000000000 && divisor == 0xFFFFFFFFFFFFFFFF) { @@ -130,7 +130,7 @@ void Interpreter::ddiv(Registers& regs, u32 instr) { } } -void Interpreter::ddivu(Registers& regs, u32 instr) { +void Interpreter::ddivu(u32 instr) { u64 dividend = regs.gpr[RS(instr)]; u64 divisor = regs.gpr[RT(instr)]; if(divisor == 0) { @@ -144,14 +144,14 @@ void Interpreter::ddivu(Registers& regs, u32 instr) { } } -void Interpreter::branch(Registers& regs, bool cond, s64 address) { +void Interpreter::branch(bool cond, s64 address) { regs.delaySlot = true; if (cond) { regs.nextPC = address; } } -void Interpreter::branch_likely(Registers& regs, bool cond, s64 address) { +void Interpreter::branch_likely(bool cond, s64 address) { regs.delaySlot = true; if (cond) { regs.nextPC = address; @@ -160,44 +160,44 @@ void Interpreter::branch_likely(Registers& regs, bool cond, s64 address) { } } -void Interpreter::b(Registers& regs, u32 instr, bool cond) { +void Interpreter::b(u32 instr, bool cond) { s64 offset = (s64)se_imm(instr) << 2; s64 address = regs.pc + offset; - branch(regs, cond, address); + branch(cond, address); } -void Interpreter::blink(Registers& regs, u32 instr, bool cond) { +void Interpreter::blink(u32 instr, bool cond) { regs.gpr[31] = regs.nextPC; s64 offset = (s64)se_imm(instr) << 2; s64 address = regs.pc + offset; - branch(regs, cond, address); + branch(cond, address); } -void Interpreter::bl(Registers& regs, u32 instr, bool cond) { +void Interpreter::bl(u32 instr, bool cond) { s64 offset = (s64)se_imm(instr) << 2; s64 address = regs.pc + offset; - branch_likely(regs, cond, address); + branch_likely(cond, address); } -void Interpreter::bllink(Registers& regs, u32 instr, bool cond) { +void Interpreter::bllink(u32 instr, bool cond) { regs.gpr[31] = regs.nextPC; s64 offset = (s64)se_imm(instr) << 2; s64 address = regs.pc + offset; - branch_likely(regs, cond, address); + branch_likely(cond, address); } -void Interpreter::lui(Registers& regs, u32 instr) { +void Interpreter::lui(u32 instr) { s64 val = (s16)instr; val <<= 16; regs.gpr[RT(instr)] = val; } -void Interpreter::lb(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::lb(Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; regs.gpr[RT(instr)] = (s8)mem.Read8(regs, address, regs.oldPC); } -void Interpreter::lh(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::lh(Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b1)) { HandleTLBException(regs, address); @@ -208,7 +208,7 @@ void Interpreter::lh(Registers& regs, Mem& mem, u32 instr) { regs.gpr[RT(instr)] = (s16)mem.Read16(regs, address, regs.oldPC); } -void Interpreter::lw(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::lw(Mem& mem, u32 instr) { s16 offset = instr; u64 address = regs.gpr[RS(instr)] + offset; if (check_address_error(address, 0b11)) { @@ -226,7 +226,7 @@ void Interpreter::lw(Registers& regs, Mem& mem, u32 instr) { } } -void Interpreter::ll(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::ll(Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; u32 physical; if (!MapVAddr(regs, LOAD, address, physical)) { @@ -240,7 +240,7 @@ void Interpreter::ll(Registers& regs, Mem& mem, u32 instr) { regs.cop0.LLAddr = physical >> 4; } -void Interpreter::lwl(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::lwl(Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr = 0; if(!MapVAddr(regs, LOAD, address, paddr)) { @@ -255,7 +255,7 @@ void Interpreter::lwl(Registers& regs, Mem& mem, u32 instr) { } } -void Interpreter::lwr(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::lwr(Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr = 0; if(!MapVAddr(regs, LOAD, address, paddr)) { @@ -270,7 +270,7 @@ void Interpreter::lwr(Registers& regs, Mem& mem, u32 instr) { } } -void Interpreter::ld(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::ld(Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b111)) { HandleTLBException(regs, address); @@ -282,7 +282,7 @@ void Interpreter::ld(Registers& regs, Mem& mem, u32 instr) { regs.gpr[RT(instr)] = value; } -void Interpreter::lld(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::lld(Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, LOAD, address, paddr)) { @@ -296,7 +296,7 @@ void Interpreter::lld(Registers& regs, Mem& mem, u32 instr) { regs.cop0.LLAddr = paddr >> 4; } -void Interpreter::ldl(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::ldl(Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr = 0; if (!MapVAddr(regs, LOAD, address, paddr)) { @@ -311,7 +311,7 @@ void Interpreter::ldl(Registers& regs, Mem& mem, u32 instr) { } } -void Interpreter::ldr(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::ldr(Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, LOAD, address, paddr)) { @@ -326,13 +326,13 @@ void Interpreter::ldr(Registers& regs, Mem& mem, u32 instr) { } } -void Interpreter::lbu(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::lbu(Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u8 value = mem.Read8(regs, address, regs.oldPC); regs.gpr[RT(instr)] = value; } -void Interpreter::lhu(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::lhu(Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b1)) { HandleTLBException(regs, address); @@ -344,7 +344,7 @@ void Interpreter::lhu(Registers& regs, Mem& mem, u32 instr) { regs.gpr[RT(instr)] = value; } -void Interpreter::lwu(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::lwu(Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b11)) { HandleTLBException(regs, address); @@ -356,12 +356,12 @@ void Interpreter::lwu(Registers& regs, Mem& mem, u32 instr) { regs.gpr[RT(instr)] = value; } -void Interpreter::sb(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::sb(Mem& mem, u32 instr) { u32 address = regs.gpr[RS(instr)] + (s16)instr; mem.Write8(regs, address, regs.gpr[RT(instr)], regs.oldPC); } -void Interpreter::sc(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::sc(Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b11)) { HandleTLBException(regs, address); @@ -376,7 +376,7 @@ void Interpreter::sc(Registers& regs, Mem& mem, u32 instr) { regs.cop0.llbit = false; } -void Interpreter::scd(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::scd(Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b111)) { HandleTLBException(regs, address); @@ -392,7 +392,7 @@ void Interpreter::scd(Registers& regs, Mem& mem, u32 instr) { regs.cop0.llbit = false; } -void Interpreter::sh(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::sh(Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b1)) { HandleTLBException(regs, address); @@ -409,7 +409,7 @@ void Interpreter::sh(Registers& regs, Mem& mem, u32 instr) { } } -void Interpreter::sw(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::sw(Mem& mem, u32 instr) { s16 offset = instr; u64 address = regs.gpr[RS(instr)] + offset; if (check_address_error(address, 0b11)) { @@ -427,7 +427,7 @@ void Interpreter::sw(Registers& regs, Mem& mem, u32 instr) { } } -void Interpreter::sd(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::sd(Mem& mem, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b11)) { HandleTLBException(regs, address); @@ -445,7 +445,7 @@ void Interpreter::sd(Registers& regs, Mem& mem, u32 instr) { } -void Interpreter::sdl(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::sdl(Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, STORE, address, paddr)) { @@ -460,7 +460,7 @@ void Interpreter::sdl(Registers& regs, Mem& mem, u32 instr) { } } -void Interpreter::sdr(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::sdr(Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, STORE, address, paddr)) { @@ -475,7 +475,7 @@ void Interpreter::sdr(Registers& regs, Mem& mem, u32 instr) { } } -void Interpreter::swl(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::swl(Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, STORE, address, paddr)) { @@ -490,7 +490,7 @@ void Interpreter::swl(Registers& regs, Mem& mem, u32 instr) { } } -void Interpreter::swr(Registers& regs, Mem& mem, u32 instr) { +void Interpreter::swr(Mem& mem, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, STORE, address, paddr)) { @@ -505,21 +505,21 @@ void Interpreter::swr(Registers& regs, Mem& mem, u32 instr) { } } -void Interpreter::ori(Registers& regs, u32 instr) { +void Interpreter::ori(u32 instr) { s64 imm = (u16)instr; s64 result = imm | regs.gpr[RS(instr)]; regs.gpr[RT(instr)] = result; } -void Interpreter::or_(Registers& regs, u32 instr) { +void Interpreter::or_(u32 instr) { regs.gpr[RD(instr)] = regs.gpr[RS(instr)] | regs.gpr[RT(instr)]; } -void Interpreter::nor(Registers& regs, u32 instr) { +void Interpreter::nor(u32 instr) { regs.gpr[RD(instr)] = ~(regs.gpr[RS(instr)] | regs.gpr[RT(instr)]); } -void Interpreter::j(Registers& regs, u32 instr) { +void Interpreter::j(u32 instr) { s32 target = (instr & 0x3ffffff) << 2; s64 address = (regs.oldPC & ~0xfffffff) | target; if (check_address_error(address, 0b11)) { @@ -527,127 +527,127 @@ void Interpreter::j(Registers& regs, u32 instr) { FireException(regs, ExceptionCode::DataBusError, 0, true); } - branch(regs, true, address); + branch(true, address); } -void Interpreter::jal(Registers& regs, u32 instr) { +void Interpreter::jal(u32 instr) { regs.gpr[31] = regs.nextPC; - j(regs, instr); + j(instr); } -void Interpreter::jalr(Registers& regs, u32 instr) { - branch(regs, true, regs.gpr[RS(instr)]); +void Interpreter::jalr(u32 instr) { + branch(true, regs.gpr[RS(instr)]); regs.gpr[RD(instr)] = regs.pc + 4; } -void Interpreter::slti(Registers& regs, u32 instr) { +void Interpreter::slti(u32 instr) { regs.gpr[RT(instr)] = regs.gpr[RS(instr)] < se_imm(instr); } -void Interpreter::sltiu(Registers& regs, u32 instr) { +void Interpreter::sltiu(u32 instr) { regs.gpr[RT(instr)] = (u64)regs.gpr[RS(instr)] < se_imm(instr); } -void Interpreter::slt(Registers& regs, u32 instr) { +void Interpreter::slt(u32 instr) { regs.gpr[RD(instr)] = regs.gpr[RS(instr)] < regs.gpr[RT(instr)]; } -void Interpreter::sltu(Registers& regs, u32 instr) { +void Interpreter::sltu(u32 instr) { regs.gpr[RD(instr)] = (u64)regs.gpr[RS(instr)] < (u64)regs.gpr[RT(instr)]; } -void Interpreter::xori(Registers& regs, u32 instr) { +void Interpreter::xori(u32 instr) { s64 imm = (u16)instr; regs.gpr[RT(instr)] = regs.gpr[RS(instr)] ^ imm; } -void Interpreter::xor_(Registers& regs, u32 instr) { +void Interpreter::xor_(u32 instr) { regs.gpr[RD(instr)] = regs.gpr[RT(instr)] ^ regs.gpr[RS(instr)]; } -void Interpreter::andi(Registers& regs, u32 instr) { +void Interpreter::andi(u32 instr) { s64 imm = (u16)instr; regs.gpr[RT(instr)] = regs.gpr[RS(instr)] & imm; } -void Interpreter::and_(Registers& regs, u32 instr) { +void Interpreter::and_(u32 instr) { regs.gpr[RD(instr)] = regs.gpr[RS(instr)] & regs.gpr[RT(instr)]; } -void Interpreter::sll(Registers& regs, u32 instr) { +void Interpreter::sll(u32 instr) { u8 sa = ((instr >> 6) & 0x1f); s32 result = regs.gpr[RT(instr)] << sa; regs.gpr[RD(instr)] = (s64)result; } -void Interpreter::sllv(Registers& regs, u32 instr) { +void Interpreter::sllv(u32 instr) { u8 sa = (regs.gpr[RS(instr)]) & 0x1F; u32 rt = regs.gpr[RT(instr)]; s32 result = rt << sa; regs.gpr[RD(instr)] = (s64)result; } -void Interpreter::dsll32(Registers& regs, u32 instr) { +void Interpreter::dsll32(u32 instr) { u8 sa = ((instr >> 6) & 0x1f); s64 result = regs.gpr[RT(instr)] << (sa + 32); regs.gpr[RD(instr)] = result; } -void Interpreter::dsll(Registers& regs, u32 instr) { +void Interpreter::dsll(u32 instr) { u8 sa = ((instr >> 6) & 0x1f); s64 result = regs.gpr[RT(instr)] << sa; regs.gpr[RD(instr)] = result; } -void Interpreter::dsllv(Registers& regs, u32 instr) { +void Interpreter::dsllv(u32 instr) { s64 sa = regs.gpr[RS(instr)] & 63; s64 result = regs.gpr[RT(instr)] << sa; regs.gpr[RD(instr)] = result; } -void Interpreter::srl(Registers& regs, u32 instr) { +void Interpreter::srl(u32 instr) { u32 rt = regs.gpr[RT(instr)]; u8 sa = ((instr >> 6) & 0x1f); u32 result = rt >> sa; regs.gpr[RD(instr)] = (s32)result; } -void Interpreter::srlv(Registers& regs, u32 instr) { +void Interpreter::srlv(u32 instr) { u8 sa = (regs.gpr[RS(instr)] & 0x1F); u32 rt = regs.gpr[RT(instr)]; s32 result = rt >> sa; regs.gpr[RD(instr)] = (s64)result; } -void Interpreter::dsrl(Registers& regs, u32 instr) { +void Interpreter::dsrl(u32 instr) { u64 rt = regs.gpr[RT(instr)]; u8 sa = ((instr >> 6) & 0x1f); u64 result = rt >> sa; regs.gpr[RD(instr)] = s64(result); } -void Interpreter::dsrlv(Registers& regs, u32 instr) { +void Interpreter::dsrlv(u32 instr) { u8 amount = (regs.gpr[RS(instr)] & 63); u64 rt = regs.gpr[RT(instr)]; u64 result = rt >> amount; regs.gpr[RD(instr)] = s64(result); } -void Interpreter::dsrl32(Registers& regs, u32 instr) { +void Interpreter::dsrl32(u32 instr) { u64 rt = regs.gpr[RT(instr)]; u8 sa = ((instr >> 6) & 0x1f); u64 result = rt >> (sa + 32); regs.gpr[RD(instr)] = s64(result); } -void Interpreter::sra(Registers& regs, u32 instr) { +void Interpreter::sra(u32 instr) { s64 rt = regs.gpr[RT(instr)]; u8 sa = ((instr >> 6) & 0x1f); s32 result = rt >> sa; regs.gpr[RD(instr)] = result; } -void Interpreter::srav(Registers& regs, u32 instr) { +void Interpreter::srav(u32 instr) { s64 rt = regs.gpr[RT(instr)]; s64 rs = regs.gpr[RS(instr)]; u8 sa = rs & 0x1f; @@ -655,14 +655,14 @@ void Interpreter::srav(Registers& regs, u32 instr) { regs.gpr[RD(instr)] = result; } -void Interpreter::dsra(Registers& regs, u32 instr) { +void Interpreter::dsra(u32 instr) { s64 rt = regs.gpr[RT(instr)]; u8 sa = ((instr >> 6) & 0x1f); s64 result = rt >> sa; regs.gpr[RD(instr)] = result; } -void Interpreter::dsrav(Registers& regs, u32 instr) { +void Interpreter::dsrav(u32 instr) { s64 rt = regs.gpr[RT(instr)]; s64 rs = regs.gpr[RS(instr)]; s64 sa = rs & 63; @@ -670,24 +670,24 @@ void Interpreter::dsrav(Registers& regs, u32 instr) { regs.gpr[RD(instr)] = result; } -void Interpreter::dsra32(Registers& regs, u32 instr) { +void Interpreter::dsra32(u32 instr) { s64 rt = regs.gpr[RT(instr)]; u8 sa = ((instr >> 6) & 0x1f); s64 result = rt >> (sa + 32); regs.gpr[RD(instr)] = result; } -void Interpreter::jr(Registers& regs, u32 instr) { +void Interpreter::jr(u32 instr) { s64 address = regs.gpr[RS(instr)]; if (check_address_error(address, 0b11)) { HandleTLBException(regs, address); FireException(regs, ExceptionCode::DataBusError, 0, regs.oldPC); } - branch(regs, true, address); + branch(true, address); } -void Interpreter::dsub(Registers& regs, u32 instr) { +void Interpreter::dsub(u32 instr) { s64 rt = regs.gpr[RT(instr)]; s64 rs = regs.gpr[RS(instr)]; s64 result = rs - rt; @@ -698,14 +698,14 @@ void Interpreter::dsub(Registers& regs, u32 instr) { } } -void Interpreter::dsubu(Registers& regs, u32 instr) { +void Interpreter::dsubu(u32 instr) { u64 rt = regs.gpr[RT(instr)]; u64 rs = regs.gpr[RS(instr)]; u64 result = rs - rt; regs.gpr[RD(instr)] = s64(result); } -void Interpreter::sub(Registers& regs, u32 instr) { +void Interpreter::sub(u32 instr) { s32 rt = regs.gpr[RT(instr)]; s32 rs = regs.gpr[RS(instr)]; s32 result = rs - rt; @@ -716,14 +716,14 @@ void Interpreter::sub(Registers& regs, u32 instr) { } } -void Interpreter::subu(Registers& regs, u32 instr) { +void Interpreter::subu(u32 instr) { u32 rt = regs.gpr[RT(instr)]; u32 rs = regs.gpr[RS(instr)]; u32 result = rs - rt; regs.gpr[RD(instr)] = (s64)((s32)result); } -void Interpreter::dmultu(Registers& regs, u32 instr) { +void Interpreter::dmultu(u32 instr) { u64 rt = regs.gpr[RT(instr)]; u64 rs = regs.gpr[RS(instr)]; u128 result = (u128)rt * (u128)rs; @@ -731,7 +731,7 @@ void Interpreter::dmultu(Registers& regs, u32 instr) { regs.hi = (s64)(result >> 64); } -void Interpreter::dmult(Registers& regs, u32 instr) { +void Interpreter::dmult(u32 instr) { s64 rt = regs.gpr[RT(instr)]; s64 rs = regs.gpr[RS(instr)]; s128 result = (s128)rt * (s128)rs; @@ -739,7 +739,7 @@ void Interpreter::dmult(Registers& regs, u32 instr) { regs.hi = result >> 64; } -void Interpreter::multu(Registers& regs, u32 instr) { +void Interpreter::multu(u32 instr) { u32 rt = regs.gpr[RT(instr)]; u32 rs = regs.gpr[RS(instr)]; u64 result = (u64)rt * (u64)rs; @@ -747,7 +747,7 @@ void Interpreter::multu(Registers& regs, u32 instr) { regs.hi = (s64)((s32)(result >> 32)); } -void Interpreter::mult(Registers& regs, u32 instr) { +void Interpreter::mult(u32 instr) { s32 rt = regs.gpr[RT(instr)]; s32 rs = regs.gpr[RS(instr)]; s64 result = (s64)rt * (s64)rs; @@ -755,50 +755,50 @@ void Interpreter::mult(Registers& regs, u32 instr) { regs.hi = (s64)((s32)(result >> 32)); } -void Interpreter::mflo(Registers& regs, u32 instr) { +void Interpreter::mflo(u32 instr) { regs.gpr[RD(instr)] = regs.lo; } -void Interpreter::mfhi(Registers& regs, u32 instr) { +void Interpreter::mfhi(u32 instr) { regs.gpr[RD(instr)] = regs.hi; } -void Interpreter::mtlo(Registers& regs, u32 instr) { +void Interpreter::mtlo(u32 instr) { regs.lo = regs.gpr[RS(instr)]; } -void Interpreter::mthi(Registers& regs, u32 instr) { +void Interpreter::mthi(u32 instr) { regs.hi = regs.gpr[RS(instr)]; } -void Interpreter::trap(Registers& regs, bool cond) { +void Interpreter::trap(bool cond) { if(cond) { FireException(regs, ExceptionCode::Trap, 0, regs.oldPC); } } -void Interpreter::mtc2(Registers& regs, u32 instr) { +void Interpreter::mtc2(u32 instr) { cop2Latch = regs.gpr[RT(instr)]; } -void Interpreter::mfc2(Registers& regs, u32 instr) { +void Interpreter::mfc2(u32 instr) { s32 value = cop2Latch; regs.gpr[RT(instr)] = value; } -void Interpreter::dmtc2(Registers& regs, u32 instr) { +void Interpreter::dmtc2(u32 instr) { cop2Latch = regs.gpr[RT(instr)]; } -void Interpreter::dmfc2(Registers& regs, u32 instr) { +void Interpreter::dmfc2(u32 instr) { regs.gpr[RT(instr)] = cop2Latch; } -void Interpreter::ctc2(Registers& regs, u32) { +void Interpreter::ctc2(u32) { } -void Interpreter::cfc2(Registers& regs, u32) { +void Interpreter::cfc2(u32) { } diff --git a/src/backend/core/registers/Cop1.cpp b/src/backend/core/registers/Cop1.cpp index f632a05c..25efe05d 100644 --- a/src/backend/core/registers/Cop1.cpp +++ b/src/backend/core/registers/Cop1.cpp @@ -35,10 +35,10 @@ void Cop1::decode(Registers& regs, Interpreter& cpu, u32 instr) { case 0x07: FireException(regs, ExceptionCode::ReservedInstruction, 1, true); break; case 0x08: switch(mask_branch) { - case 0: cpu.b(regs, instr, !regs.cop1.fcr31.compare); break; - case 1: cpu.b(regs, instr, regs.cop1.fcr31.compare); break; - case 2: cpu.bl(regs, instr, !regs.cop1.fcr31.compare); break; - case 3: cpu.bl(regs, instr, regs.cop1.fcr31.compare); break; + case 0: cpu.b(instr, !regs.cop1.fcr31.compare); break; + case 1: cpu.b(instr, regs.cop1.fcr31.compare); break; + case 2: cpu.bl(instr, !regs.cop1.fcr31.compare); break; + case 3: cpu.bl(instr, regs.cop1.fcr31.compare); break; default: Util::panic("Undefined BC COP1 {:02X}\n", mask_branch); } break; diff --git a/src/backend/core/rsp/decode.cpp b/src/backend/core/rsp/decode.cpp index 114409aa..6fd1bb32 100644 --- a/src/backend/core/rsp/decode.cpp +++ b/src/backend/core/rsp/decode.cpp @@ -86,6 +86,7 @@ inline void swc2(RSP& rsp, u32 instr) { case 0x04: rsp.sqv(instr); break; case 0x06: rsp.spv(instr); break; case 0x07: rsp.suv(instr); break; + case 0x09: rsp.sfv(instr); break; case 0x0A: rsp.swv(instr); break; case 0x0B: rsp.stv(instr); break; default: Util::panic("Unhandled RSP SWC2 {:05b}\n", mask); diff --git a/src/backend/core/rsp/instructions.cpp b/src/backend/core/rsp/instructions.cpp index 1d1bddf2..ce2eea23 100644 --- a/src/backend/core/rsp/instructions.cpp +++ b/src/backend/core/rsp/instructions.cpp @@ -420,6 +420,68 @@ void RSP::spv(u32 instr) { } } +void RSP::sfv(u32 instr) { + VPR& vt = vpr[VT(instr)]; + u32 address = gpr[BASE(instr)] + SignExt7bit(OFFSET(instr), 4); + int base = address & 7; + address &= ~7; + int e = E1(instr); + + u8 values[4] = {0, 0, 0, 0}; + + switch (e) { + case 0: + case 15: + values[0] = vt.element[ELEMENT_INDEX(0)] >> 7; + values[1] = vt.element[ELEMENT_INDEX(1)] >> 7; + values[2] = vt.element[ELEMENT_INDEX(2)] >> 7; + values[3] = vt.element[ELEMENT_INDEX(3)] >> 7; + break; + case 1: + values[0] = vt.element[ELEMENT_INDEX(6)] >> 7; + values[1] = vt.element[ELEMENT_INDEX(7)] >> 7; + values[2] = vt.element[ELEMENT_INDEX(4)] >> 7; + values[3] = vt.element[ELEMENT_INDEX(5)] >> 7; + break; + case 4: + values[0] = vt.element[ELEMENT_INDEX(1)] >> 7; + values[1] = vt.element[ELEMENT_INDEX(2)] >> 7; + values[2] = vt.element[ELEMENT_INDEX(3)] >> 7; + values[3] = vt.element[ELEMENT_INDEX(0)] >> 7; + break; + case 5: + values[0] = vt.element[ELEMENT_INDEX(7)] >> 7; + values[1] = vt.element[ELEMENT_INDEX(4)] >> 7; + values[2] = vt.element[ELEMENT_INDEX(5)] >> 7; + values[3] = vt.element[ELEMENT_INDEX(6)] >> 7; + break; + case 8: + values[0] = vt.element[ELEMENT_INDEX(4)] >> 7; + values[1] = vt.element[ELEMENT_INDEX(5)] >> 7; + values[2] = vt.element[ELEMENT_INDEX(6)] >> 7; + values[3] = vt.element[ELEMENT_INDEX(7)] >> 7; + break; + case 11: + values[0] = vt.element[ELEMENT_INDEX(3)] >> 7; + values[1] = vt.element[ELEMENT_INDEX(0)] >> 7; + values[2] = vt.element[ELEMENT_INDEX(1)] >> 7; + values[3] = vt.element[ELEMENT_INDEX(2)] >> 7; + break; + case 12: + values[0] = vt.element[ELEMENT_INDEX(5)] >> 7; + values[1] = vt.element[ELEMENT_INDEX(6)] >> 7; + values[2] = vt.element[ELEMENT_INDEX(7)] >> 7; + values[3] = vt.element[ELEMENT_INDEX(4)] >> 7; + break; + default: + break; + } + + for (int i = 0; i < 4; i++) { + WriteByte(address + ((base + (i << 2)) & 15), values[i]); + } +} + void RSP::sbv(u32 instr) { int e = E1(instr); u32 addr = gpr[BASE(instr)] + SignExt7bit(OFFSET(instr), 0); diff --git a/src/frontend/imgui/Settings.cpp b/src/frontend/imgui/Settings.cpp index bdf1c20d..37c8219b 100644 --- a/src/frontend/imgui/Settings.cpp +++ b/src/frontend/imgui/Settings.cpp @@ -65,6 +65,13 @@ Settings::Settings(n64::Core& core) { settingsFile << settings; } settingsFile.close(); + + switch(core.cpuType) { + case n64::CpuType::Interpreter: core.cpuInterp = new n64::Interpreter; break; + case n64::CpuType::Dynarec: core.cpuDynarec = new n64::JIT::Dynarec; break; + case n64::CpuType::NONE: + Util::panic("BRUH\n"); + } } Settings::~Settings() { @@ -100,7 +107,7 @@ void Settings::RenderWidget(bool& show) { const char *categories[] = {"General", "CPU", "Audio"}; enum Category { General, CPU, Audio }; static int category = General; - CreateComboList("", &category, categories, 3); + CreateComboList("##", &category, categories, 3); ImGui::Separator(); switch (category) { case General: diff --git a/src/frontend/imgui/Window.hpp b/src/frontend/imgui/Window.hpp index 9d4903da..bba80f81 100644 --- a/src/frontend/imgui/Window.hpp +++ b/src/frontend/imgui/Window.hpp @@ -1,4 +1,5 @@ #pragma once +#define SDL_MAIN_HANDLED #include #include #include diff --git a/src/main.cpp b/src/main.cpp index d71a6b21..4545737d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,10 +1,6 @@ #include #include -#ifdef _WIN32 -#define main SDL_main -#endif - int main(int argc, char** argv) { App* app = new App; if(argc > 1) { diff --git a/src/utils/MemoryHelpers.hpp b/src/utils/MemoryHelpers.hpp index 71bb3d97..f284667a 100644 --- a/src/utils/MemoryHelpers.hpp +++ b/src/utils/MemoryHelpers.hpp @@ -91,7 +91,7 @@ inline void* aligned_alloc(size_t alignment, size_t size) { return _aligned_malloc(size, alignment); } -inline void free(void* ptr) { +inline void aligned_free(void* ptr) { _aligned_free(ptr); } #else @@ -99,7 +99,7 @@ inline void* aligned_alloc(size_t alignment, size_t size) { return std::aligned_alloc(alignment, size); } -inline void free(void* ptr) { +inline void aligned_free(void* ptr) { std::free(ptr); } #endif