From 30fce7ecf7c06c2139610fdcc3f3b422283722a7 Mon Sep 17 00:00:00 2001 From: SimoneN64 Date: Sun, 4 Jun 2023 22:28:23 +0200 Subject: [PATCH] get rid of JIT and other things --- src/CMakeLists.txt | 3 +- src/backend/Core.cpp | 84 +- src/backend/Core.hpp | 15 +- src/backend/Debugger.cpp | 1 - src/backend/Debugger.hpp | 32 - src/backend/core/BaseCPU.hpp | 15 - src/backend/core/Interpreter.cpp | 52 - src/backend/core/Interpreter.hpp | 55 +- src/backend/core/JIT.cpp | 133 --- src/backend/core/JIT.hpp | 42 - src/backend/core/Mem.cpp | 21 - src/backend/core/Mem.hpp | 8 +- src/backend/core/RSP.cpp | 24 - src/backend/core/RSP.hpp | 12 +- src/backend/core/jit/CMakeLists.txt | 4 - src/backend/core/jit/MemoryManagement.cpp | 27 - src/backend/core/jit/cop/cop0decode.cpp | 61 - src/backend/core/jit/cop/cop0decode.hpp | 7 - src/backend/core/jit/cop/cop0instructions.cpp | 89 -- src/backend/core/jit/cop/cop0instructions.hpp | 13 - src/backend/core/jit/cop/cop1decode.cpp | 464 -------- src/backend/core/jit/cop/cop1decode.hpp | 6 - src/backend/core/jit/cop/cop1instructions.cpp | 617 ---------- src/backend/core/jit/cop/cop1instructions.hpp | 68 -- src/backend/core/jit/decode.cpp | 655 ---------- src/backend/core/jit/instructions.cpp | 1051 ----------------- src/backend/core/jit/instructions.hpp | 94 -- src/backend/core/mmio/PIF.cpp | 1 + src/backend/core/mmio/PIF/Device.cpp | 6 +- src/backend/core/mmio/VI.cpp | 2 +- src/backend/core/mmio/VI.hpp | 1 + src/common.hpp | 2 +- src/frontend/App.cpp | 11 +- src/frontend/imgui/Settings.cpp | 53 +- src/frontend/imgui/Settings.hpp | 2 - src/frontend/imgui/Window.cpp | 14 +- 36 files changed, 143 insertions(+), 3602 deletions(-) delete mode 100644 src/backend/Debugger.cpp delete mode 100644 src/backend/Debugger.hpp delete mode 100644 src/backend/core/BaseCPU.hpp delete mode 100644 src/backend/core/JIT.cpp delete mode 100644 src/backend/core/JIT.hpp delete mode 100644 src/backend/core/jit/CMakeLists.txt delete mode 100644 src/backend/core/jit/MemoryManagement.cpp delete mode 100644 src/backend/core/jit/cop/cop0decode.cpp delete mode 100644 src/backend/core/jit/cop/cop0decode.hpp delete mode 100644 src/backend/core/jit/cop/cop0instructions.cpp delete mode 100644 src/backend/core/jit/cop/cop0instructions.hpp delete mode 100644 src/backend/core/jit/cop/cop1decode.cpp delete mode 100644 src/backend/core/jit/cop/cop1decode.hpp delete mode 100644 src/backend/core/jit/cop/cop1instructions.cpp delete mode 100644 src/backend/core/jit/cop/cop1instructions.hpp delete mode 100644 src/backend/core/jit/decode.cpp delete mode 100644 src/backend/core/jit/instructions.cpp delete mode 100644 src/backend/core/jit/instructions.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4191e5c4..593ec405 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -49,7 +49,6 @@ add_subdirectory(frontend) add_subdirectory(frontend/imgui) add_subdirectory(backend) add_subdirectory(backend/core) -add_subdirectory(backend/core/jit) add_subdirectory(backend/core/interpreter) add_subdirectory(backend/core/mmio) add_subdirectory(backend/core/registers) @@ -68,7 +67,7 @@ file(REMOVE ${PROJECT_BINARY_DIR}/resources/shader.vert) target_link_libraries(kaizen PUBLIC frontend frontend-imgui - discord-rpc imgui nfd parallel-rdp backend fmt::fmt nlohmann_json::nlohmann_json core jit registers interpreter mmio rsp SDL2::SDL2main SDL2::SDL2) + discord-rpc imgui nfd parallel-rdp backend fmt::fmt nlohmann_json::nlohmann_json core registers interpreter mmio rsp SDL2::SDL2main SDL2::SDL2) if(WIN32) target_compile_definitions(kaizen PUBLIC NOMINMAX _CRT_SECURE_NO_WARNINGS) diff --git a/src/backend/Core.cpp b/src/backend/Core.cpp index 6e5a88bd..6bd8493f 100644 --- a/src/backend/Core.cpp +++ b/src/backend/Core.cpp @@ -11,59 +11,75 @@ Core::Core() { } void Core::Stop() { - cpu->Reset(); - cpu->mem.Reset(); + cpu.Reset(); + cpu.mem.Reset(); pause = true; romLoaded = false; } void Core::LoadROM(const std::string& rom_) { rom = rom_; - cpu->Reset(); - cpu->mem.Reset(); + cpu.Reset(); + cpu.mem.Reset(); pause = false; romLoaded = true; - cpu->mem.LoadROM(rom); - GameDB::match(cpu->mem); - cpu->mem.mmio.si.pif.InitDevices(cpu->mem.saveType); - cpu->mem.mmio.si.pif.LoadMempak(rom_); - cpu->mem.mmio.si.pif.LoadEeprom(cpu->mem.saveType, rom_); - isPAL = cpu->mem.IsROMPAL(); - cpu->mem.mmio.si.pif.ExecutePIF(cpu->mem, cpu->regs); + cpu.mem.LoadROM(rom); + GameDB::match(cpu.mem); + cpu.mem.mmio.si.pif.InitDevices(cpu.mem.saveType); + cpu.mem.mmio.si.pif.LoadMempak(rom_); + cpu.mem.mmio.si.pif.LoadEeprom(cpu.mem.saveType, rom_); + isPAL = cpu.mem.IsROMPAL(); + cpu.mem.mmio.vi.isPal = isPAL; + cpu.mem.mmio.si.pif.ExecutePIF(cpu.mem, cpu.regs); } -void Core::Run(Window& window, float volumeL, float volumeR) { - MMIO& mmio = cpu->mem.mmio; +void Core::Run(float volumeL, float volumeR) { + Mem& mem = cpu.mem; + MMIO& mmio = mem.mmio; + Registers& regs = cpu.regs; for (int field = 0; field < mmio.vi.numFields; field++) { - if (!pause && romLoaded) { - int frameCycles = 0; - for (int i = 0; i < mmio.vi.numHalflines; i++) { - mmio.vi.current = (i << 1) + field; - - if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) { - InterruptRaise(mmio.mi, cpu->regs, Interrupt::VI); - } - - int cpuCount = cpu->Run(); - cpu->RunRSP(cpuCount); - frameCycles += cpuCount; - } + int frameCycles = 0; + for (int i = 0; i < mmio.vi.numHalflines; i++) { + mmio.vi.current = (i << 1) + field; if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) { - InterruptRaise(mmio.mi, cpu->regs, Interrupt::VI); + InterruptRaise(mmio.mi, regs, Interrupt::VI); } - UpdateScreenParallelRdp(*this, window, GetVI()); + for(; cycles < mem.mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) { + int taken = cpu.Step(); + static int cpuSteps = 0; + cpuSteps += taken; + if(mmio.rsp.spStatus.halt) { + cpuSteps = 0; + mmio.rsp.steps = 0; + } else { + while(cpuSteps > 2) { + mmio.rsp.steps += 2; + cpuSteps -= 3; + } - mmio.ai.Step(cpu->mem, cpu->regs, frameCycles, volumeL, volumeR); - scheduler.tick(frameCycles, cpu->mem, cpu->regs); - } else if (pause && romLoaded) { - UpdateScreenParallelRdp(*this, window, GetVI()); - } else if (pause && !romLoaded) { - UpdateScreenParallelRdpNoGame(*this, window); + while(mmio.rsp.steps > 0) { + mmio.rsp.steps--; + mmio.rsp.Step(regs, mem); + } + } + + cycles += taken; + frameCycles += taken; + } + + cycles -= mmio.vi.cyclesPerHalfline; } + + if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) { + InterruptRaise(mmio.mi, regs, Interrupt::VI); + } + + mmio.ai.Step(cpu.mem, regs, frameCycles, volumeL, volumeR); + scheduler.tick(frameCycles, mem, regs); } } } diff --git a/src/backend/Core.hpp b/src/backend/Core.hpp index df01d5eb..ec370991 100644 --- a/src/backend/Core.hpp +++ b/src/backend/Core.hpp @@ -3,36 +3,29 @@ #include #include #include -#include #include -#include #include struct Window; namespace n64 { -enum class CpuType { - Interpreter, JIT, COUNT -}; - struct Core { ~Core() { Stop(); } Core(); void Stop(); void LoadROM(const std::string&); - void Run(Window&, float volumeL, float volumeR); + void Run(float volumeL, float volumeR); void TogglePause() { pause = !pause; } - VI& GetVI() { return cpu->mem.mmio.vi; } + VI& GetVI() { return cpu.mem.mmio.vi; } u32 breakpoint = 0; bool pause = true; + int cycles = 0; bool isPAL = false; bool romLoaded = false; bool done = false; std::string rom; - CpuType cpuType = CpuType::COUNT; - std::unique_ptr cpu; - Debugger debugger{*this}; + Interpreter cpu; }; } diff --git a/src/backend/Debugger.cpp b/src/backend/Debugger.cpp deleted file mode 100644 index 3cebb007..00000000 --- a/src/backend/Debugger.cpp +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/src/backend/Debugger.hpp b/src/backend/Debugger.hpp deleted file mode 100644 index 9ff3da17..00000000 --- a/src/backend/Debugger.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once -#include - -struct Breakpoint { - u32 address = 0; - Breakpoint* next = nullptr; -}; - -namespace n64 { struct Core; } - -struct Debugger { - Debugger(n64::Core& core) :core(core) {} - ~Debugger() = default; - - bool broken = false, enabled = true; - Breakpoint* breakpoints = nullptr; - n64::Core& core; - - [[nodiscard]] inline bool checkBreakpoint(u32 address) const { - auto* cur = breakpoints; - while (cur != nullptr) { - if (cur->address == address) { - return true; - } - cur = cur->next; - } - return false; - } - - void tick() const {} - void breakpointHit() {} -}; \ No newline at end of file diff --git a/src/backend/core/BaseCPU.hpp b/src/backend/core/BaseCPU.hpp deleted file mode 100644 index f4d3ac74..00000000 --- a/src/backend/core/BaseCPU.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include - -namespace n64 { -struct BaseCPU { - virtual ~BaseCPU() {} - virtual void Reset() {} - virtual int Run() {} - void RunRSP(int cpuCount) { - mem.mmio.rsp.Run(cpuCount, regs, mem); - } - Registers regs; - Mem mem; -}; -} \ No newline at end of file diff --git a/src/backend/core/Interpreter.cpp b/src/backend/core/Interpreter.cpp index 13c33e87..01922aae 100644 --- a/src/backend/core/Interpreter.cpp +++ b/src/backend/core/Interpreter.cpp @@ -1,59 +1,7 @@ #include -#include namespace n64 { -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 Interpreter::Reset() { regs.Reset(); } - -int Interpreter::Run() { - int cycles = 1; - for(; cycles < mem.mmio.vi.cyclesPerHalfline; cycles++) { - CheckCompareInterrupt(mem.mmio.mi, regs); - - regs.prevDelaySlot = regs.delaySlot; - regs.delaySlot = false; - - u32 paddr = 0; - if(!MapVAddr(regs, LOAD, regs.pc, paddr)) { - HandleTLBException(regs, regs.pc); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false); - return cycles; - } - - u32 instruction = mem.Read32(regs, paddr); - - if(ShouldServiceInterrupt(regs)) { - FireException(regs, ExceptionCode::Interrupt, 0, false); - return cycles; - } - - regs.oldPC = regs.pc; - regs.pc = regs.nextPC; - regs.nextPC += 4; - - Exec(instruction); - } - - return cycles; -} } \ No newline at end of file diff --git a/src/backend/core/Interpreter.hpp b/src/backend/core/Interpreter.hpp index 24aeb114..d0db0095 100644 --- a/src/backend/core/Interpreter.hpp +++ b/src/backend/core/Interpreter.hpp @@ -2,19 +2,66 @@ #include #include #include -#include namespace n64 { struct Core; -struct Interpreter : BaseCPU { +struct Interpreter { Interpreter() = default; ~Interpreter() = default; - int Run() override; - void Reset() override; + FORCE_INLINE int Step() { + CheckCompareInterrupt(); + + regs.prevDelaySlot = regs.delaySlot; + regs.delaySlot = false; + + u32 paddr = 0; + if(!MapVAddr(regs, LOAD, regs.pc, paddr)) { + HandleTLBException(regs, regs.pc); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false); + return 0; + } + + u32 instruction = mem.Read32(regs, paddr); + + if(ShouldServiceInterrupt()) { + FireException(regs, ExceptionCode::Interrupt, 0, false); + return 0; + } + + regs.oldPC = regs.pc; + regs.pc = regs.nextPC; + regs.nextPC += 4; + + Exec(instruction); + + return 1; + } + void Reset(); + Registers regs; + Mem mem; private: u64 cop2Latch{}; friend struct Cop1; + [[nodiscard]] FORCE_INLINE bool ShouldServiceInterrupt() const { + 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; + } + + FORCE_INLINE void CheckCompareInterrupt() { + regs.cop0.count++; + regs.cop0.count &= 0x1FFFFFFFF; + if(regs.cop0.count == (u64)regs.cop0.compare << 1) { + regs.cop0.cause.ip7 = 1; + UpdateInterrupt(mem.mmio.mi, regs); + } + } + void cop2Decode(u32); void special(u32); void regimm(u32); diff --git a/src/backend/core/JIT.cpp b/src/backend/core/JIT.cpp deleted file mode 100644 index 5fe6a552..00000000 --- a/src/backend/core/JIT.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#include -#include -#include - -namespace n64 { -namespace fs = std::filesystem; - -JIT::~JIT() { - Util::aligned_free(codeCache); - dump.close(); -} - -JIT::JIT() : code(CODECACHE_SIZE, codeCache) { - codeCache = (u8*)Util::aligned_alloc(4096, CODECACHE_SIZE); - CodeArray::protect( - 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); - regs.Reset(); -} - -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 JIT::Recompile(Mem& mem, u32 pc) { - bool branch = false, prevBranch = false; - u32 startPC = pc; - u32 loopPC = pc; - Fn block = code.getCurr(); - - if(code.getSize() >= CODECACHE_OVERHEAD) { - Util::debug("Code cache overflow!\n"); - code.setSize(0); - InvalidateCache(); - } - - code.sub(rsp, 8); - - while(!prevBranch) { - instrInBlock++; - prevBranch = branch; - u32 instr = mem.Read32(regs, loopPC); - loopPC += 4; - - code.mov(rdi, (uintptr_t)this); - code.mov(qword[rdi + GPR_OFFSET(0, this)], 0); - code.mov(r8, qword[rdi + REG_OFFSET(oldPC, this)]); - code.mov(r9, qword[rdi + REG_OFFSET(pc, this)]); - code.mov(r10, qword[rdi + REG_OFFSET(nextPC, this)]); - code.mov(r8, r9); - code.mov(r9, r10); - code.add(r10, 4); - code.mov(qword[rdi + REG_OFFSET(oldPC, this)], r8); - code.mov(qword[rdi + REG_OFFSET(pc, this)], r9); - code.mov( qword[rdi + REG_OFFSET(nextPC, this)], r10); - - code.mov(esi, instr); - branch = Exec(mem, instr); - } - - code.add(rsp, 8); - code.ret(); - dump.write(code.getCode(), code.getSize()); - - blockCache[startPC >> 20][startPC & 0xFFF] = block; -} - -void JIT::AllocateOuter(u32 pc) { - blockCache[pc >> 20] = (Fn*)bumpAlloc(0x1000 * sizeof(Fn)); -} - -int JIT::Run() { - instrInBlock = 0; - regs.prevDelaySlot = regs.delaySlot; - regs.delaySlot = false; - - u32 pc{}; - - if(!MapVAddr(regs, LOAD, regs.pc, pc)) { - HandleTLBException(regs, regs.pc); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false); - return 0; - } - - if(!blockCache[pc >> 20]) { - AllocateOuter(pc); - } - - if(!blockCache[pc >> 20][pc & 0xfff]) { - Recompile(mem, pc); - } - - CheckCompareInterrupt(mem.mmio.mi, regs); - if(ShouldServiceInterrupt(regs)) { - FireException(regs, ExceptionCode::Interrupt, 0, false); - return 0; - } - - blockCache[pc >> 20][pc & 0xfff](); - - return instrInBlock; -} - -void JIT::Reset() { - code.reset(); - regs.Reset(); - InvalidateCache(); -} -} \ No newline at end of file diff --git a/src/backend/core/JIT.hpp b/src/backend/core/JIT.hpp deleted file mode 100644 index 85c65e62..00000000 --- a/src/backend/core/JIT.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace n64 { -using namespace Xbyak; -using namespace Xbyak::util; -using Fn = void (*)(); - -#define GPR_OFFSET(x, jit) ((uintptr_t)®s.gpr[(x)] - (uintptr_t)jit) -#define REG_OFFSET(kind, jit) ((uintptr_t)®s.kind - (uintptr_t)jit) -#define CODECACHE_SIZE (2 << 25) -#define CODECACHE_OVERHEAD (CODECACHE_SIZE - 1_kb) - -struct JIT : BaseCPU { - JIT(); - ~JIT() override; - int Run() override; - void Reset() override; - u64 cop2Latch{}; - CodeGenerator code; - void InvalidatePage(u32); - void InvalidateCache(); -private: - friend struct n64::Cop1; - Fn* blockCache[0x80000]{}; - u8* codeCache; - int instrInBlock = 0; - u64 sizeUsed = 0; - std::ofstream dump; - - void* bumpAlloc(u64 size, u8 val = 0); - void Recompile(Mem&, u32 pc); - void AllocateOuter(u32 pc); - void cop2Decode(u32); - bool special(u32); - bool regimm(u32); - bool Exec(Mem&, u32); -}; -} diff --git a/src/backend/core/Mem.cpp b/src/backend/core/Mem.cpp index 46b25c7a..d887e0e1 100644 --- a/src/backend/core/Mem.cpp +++ b/src/backend/core/Mem.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include namespace n64 { @@ -254,26 +253,6 @@ u64 Mem::Read64(n64::Registers ®s, u32 paddr) { } } -void Mem::Write8(Registers& regs, JIT& dyn, u32 paddr, u32 val) { - dyn.InvalidatePage(BYTE_ADDRESS(paddr)); - return Write8(regs, paddr, val); -} - -void Mem::Write16(Registers& regs, JIT& dyn, u32 paddr, u32 val) { - dyn.InvalidatePage(HALF_ADDRESS(paddr)); - return Write16(regs, paddr, val); -} - -void Mem::Write32(Registers& regs, JIT& dyn, u32 paddr, u32 val) { - dyn.InvalidatePage(paddr); - return Write32(regs, paddr, val); -} - -void Mem::Write64(Registers& regs, JIT& dyn, u32 paddr, u64 val) { - dyn.InvalidatePage(paddr); - return Write64(regs, paddr, val); -} - void Mem::Write8(Registers& regs, u32 paddr, u32 val) { const auto page = paddr >> 12; auto offset = paddr & 0xFFF; diff --git a/src/backend/core/Mem.hpp b/src/backend/core/Mem.hpp index a128c12f..12169b5b 100644 --- a/src/backend/core/Mem.hpp +++ b/src/backend/core/Mem.hpp @@ -16,8 +16,6 @@ struct CartInfo { u32 crc; }; -struct JIT; - struct ROMHeader { u8 initialValues[4]; u32 clockRate; @@ -61,10 +59,6 @@ struct Mem { u16 Read16(Registers&, u32); u32 Read32(Registers&, u32); u64 Read64(Registers&, u32); - void Write8(Registers&, JIT&, u32, u32); - void Write16(Registers&, JIT&, u32, u32); - void Write32(Registers&, JIT&, u32, u32); - void Write64(Registers&, JIT&, u32, u64); void Write8(Registers&, u32, u32); void Write16(Registers&, u32, u32); void Write32(Registers&, u32, u32); @@ -116,7 +110,7 @@ private: bool IsROMPAL() { static const char pal_codes[] = {'D', 'F', 'I', 'P', 'S', 'U', 'X', 'Y'}; return std::any_of(std::begin(pal_codes), std::end(pal_codes), [this](char a) { - return rom.cart[0x3e] == a; + return rom.cart[0x3d] == a; }); } }; diff --git a/src/backend/core/RSP.cpp b/src/backend/core/RSP.cpp index 2bafb437..f973dcd1 100644 --- a/src/backend/core/RSP.cpp +++ b/src/backend/core/RSP.cpp @@ -66,30 +66,6 @@ inline void logRSP(const RSP& rsp, const u32 instr) { } */ -void RSP::Run(int cpuCount, Registers& regs, Mem& mem) { - while(cpuCount--) { - if (!spStatus.halt) { - regs.steps++; - if (regs.steps > 2) { - steps += 2; - regs.steps -= 3; - } - - while (steps > 0) { - steps--; - gpr[0] = 0; - u32 instr = Util::ReadAccess(imem, pc & IMEM_DSIZE); - oldPC = pc & 0xFFC; - pc = nextPC & 0xFFC; - nextPC += 4; - - Exec(regs, mem, instr); - //logRSP(*this, instr); - } - } - } -} - auto RSP::Read(u32 addr) -> u32{ switch (addr) { case 0x04040000: return lastSuccessfulSPAddr.raw & 0x1FF8; diff --git a/src/backend/core/RSP.hpp b/src/backend/core/RSP.hpp index 485a02cf..56697357 100644 --- a/src/backend/core/RSP.hpp +++ b/src/backend/core/RSP.hpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #define RSP_BYTE(addr) (dmem[BYTE_ADDRESS(addr) & 0xFFF]) @@ -113,7 +114,16 @@ struct Registers; struct RSP { RSP(); void Reset(); - void Run(int, Registers& regs, Mem& mem); + + FORCE_INLINE void Step(Registers& regs, Mem& mem) { + gpr[0] = 0; + u32 instr = Util::ReadAccess(imem, pc & IMEM_DSIZE); + oldPC = pc & 0xFFC; + pc = nextPC & 0xFFC; + nextPC += 4; + + Exec(regs, mem, instr); + } auto Read(u32 addr) -> u32; void Write(Mem& mem, Registers& regs, u32 addr, u32 value); void Exec(Registers& regs, Mem& mem, u32 instr); diff --git a/src/backend/core/jit/CMakeLists.txt b/src/backend/core/jit/CMakeLists.txt deleted file mode 100644 index 9042a394..00000000 --- a/src/backend/core/jit/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -file(GLOB_RECURSE SOURCES *.cpp) -file(GLOB_RECURSE HEADERS *.hpp) - -add_library(jit ${SOURCES} ${HEADERS}) \ No newline at end of file diff --git a/src/backend/core/jit/MemoryManagement.cpp b/src/backend/core/jit/MemoryManagement.cpp deleted file mode 100644 index 5a182a7f..00000000 --- a/src/backend/core/jit/MemoryManagement.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include - -namespace n64 { -void JIT::InvalidatePage(u32 paddr) { - blockCache[paddr >> 20] = nullptr; -} - -void JIT::InvalidateCache() { - sizeUsed = 0; - for(auto &i : blockCache) { - i = nullptr; - } -} - -void* JIT::bumpAlloc(u64 size, u8 val) { - if(sizeUsed + size >= CODECACHE_SIZE) { - InvalidateCache(); - } - - void* ptr = &codeCache[sizeUsed]; - sizeUsed += size; - - memset(ptr, val, size); - - return ptr; -} -} \ No newline at end of file diff --git a/src/backend/core/jit/cop/cop0decode.cpp b/src/backend/core/jit/cop/cop0decode.cpp deleted file mode 100644 index 1a4932c4..00000000 --- a/src/backend/core/jit/cop/cop0decode.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include - -namespace n64 { -void cop0Decode(JIT& cpu, u32 instr) { - u8 mask_cop = (instr >> 21) & 0x1F; - u8 mask_cop2 = instr & 0x3F; - Xbyak::CodeGenerator& code = cpu.code; - Registers& regs = cpu.regs; - - switch(mask_cop) { - case 0x00: - code.mov(code.rax, (u64)mfc0); - code.call(code.rax); - break; - case 0x01: - code.mov(code.rax, (u64)dmfc0); - code.call(code.rax); - break; - case 0x04: - code.mov(code.rax, (uintptr_t)mtc0); - code.call(code.rax); - break; - case 0x05: - code.mov(code.rax, (u64)dmtc0); - code.call(code.rax); - break; - case 0x10 ... 0x1F: - switch(mask_cop2) { - case 0x01: - code.mov(code.rax, (u64)tlbr); - code.call(code.rax); - break; - case 0x02: - code.mov(code.rcx, code.dword[code.rdi + REG_OFFSET(cop0.index, &cpu)]); - code.and_(code.rcx, 0x3F); - code.mov(code.rsi, code.rcx); - code.mov(code.rax, (u64)tlbw); - code.call(code.rax); - break; - case 0x06: - code.mov(code.rsi, (u64)regs.cop0.GetRandom()); - code.mov(code.rax, (u64)tlbw); - code.call(code.rax); - break; - case 0x08: - code.mov(code.rax, (u64)tlbp); - code.call(code.rax); - break; - case 0x18: - code.mov(code.rax, (u64)eret); - code.call(code.rax); - break; - default: Util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016lX})", mask_cop2 >> 3, mask_cop2 & 7, instr, regs.oldPC); - } - break; - default: Util::panic("Unimplemented COP0 instruction {} {}", mask_cop >> 4, mask_cop & 7); - } -} -} \ No newline at end of file diff --git a/src/backend/core/jit/cop/cop0decode.hpp b/src/backend/core/jit/cop/cop0decode.hpp deleted file mode 100644 index 9457f038..00000000 --- a/src/backend/core/jit/cop/cop0decode.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include - -namespace n64 { -struct Registers; -void cop0Decode(JIT& cpu, u32 instr); -} \ No newline at end of file diff --git a/src/backend/core/jit/cop/cop0instructions.cpp b/src/backend/core/jit/cop/cop0instructions.cpp deleted file mode 100644 index 67df143f..00000000 --- a/src/backend/core/jit/cop/cop0instructions.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include -#include - -namespace n64 { -void mtc0(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; - regs.cop0.SetReg32(RD(instr), regs.gpr[RT(instr)]); -} - -void dmtc0(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; - regs.cop0.SetReg64(RD(instr), regs.gpr[RT(instr)]); -} - -void mfc0(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; - regs.gpr[RT(instr)] = s32(regs.cop0.GetReg32(RD(instr))); -} - -void dmfc0(JIT& cpu, u32 instr) { - Registers& regs = cpu.regs; - regs.gpr[RT(instr)] = s64(regs.cop0.GetReg64(RD(instr))); -} - -void eret(JIT& cpu) { - Registers& regs = cpu.regs; - if(regs.cop0.status.erl) { - regs.SetPC64(regs.cop0.ErrorEPC); - regs.cop0.status.erl = false; - } else { - regs.SetPC64(regs.cop0.EPC); - regs.cop0.status.exl = false; - } - regs.cop0.llbit = false; -} - - -void tlbr(JIT& cpu) { - Registers& regs = cpu.regs; - u8 Index = regs.cop0.index & 0b111111; - if (Index >= 32) { - Util::panic("TLBR with TLB index {}", Index); - } - - TLBEntry entry = regs.cop0.tlb[Index]; - - regs.cop0.entryHi.raw = entry.entryHi.raw; - regs.cop0.entryLo0.raw = entry.entryLo0.raw & 0x3FFFFFFF; - regs.cop0.entryLo1.raw = entry.entryLo1.raw & 0x3FFFFFFF; - - regs.cop0.entryLo0.g = entry.global; - regs.cop0.entryLo1.g = entry.global; - regs.cop0.pageMask.raw = entry.pageMask.raw; -} - -void tlbw(JIT& cpu, int index_) { - Registers& regs = cpu.regs; - PageMask page_mask = regs.cop0.pageMask; - u32 top = page_mask.mask & 0xAAA; - page_mask.mask = top | (top >> 1); - - if(index_ >= 32) { - Util::panic("TLBWI with TLB index {}", index_); - } - - regs.cop0.tlb[index_].entryHi.raw = regs.cop0.entryHi.raw; - regs.cop0.tlb[index_].entryHi.vpn2 &= ~page_mask.mask; - - regs.cop0.tlb[index_].entryLo0.raw = regs.cop0.entryLo0.raw & 0x03FFFFFE; - regs.cop0.tlb[index_].entryLo1.raw = regs.cop0.entryLo1.raw & 0x03FFFFFE; - regs.cop0.tlb[index_].pageMask.raw = page_mask.raw; - - regs.cop0.tlb[index_].global = regs.cop0.entryLo0.g && regs.cop0.entryLo1.g; - regs.cop0.tlb[index_].initialized = true; -} - -void tlbp(JIT& cpu) { - Registers& regs = cpu.regs; - int match = -1; - TLBEntry* entry = TLBTryMatch(regs, regs.cop0.entryHi.raw, &match); - if(entry && match >= 0) { - regs.cop0.index = match; - } else { - regs.cop0.index = 0x80000000; - } -} - -} \ No newline at end of file diff --git a/src/backend/core/jit/cop/cop0instructions.hpp b/src/backend/core/jit/cop/cop0instructions.hpp deleted file mode 100644 index 768449dc..00000000 --- a/src/backend/core/jit/cop/cop0instructions.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include - -namespace n64 { -void mtc0(JIT&, u32); -void dmtc0(JIT&, u32); -void mfc0(JIT&, u32); -void dmfc0(JIT&, u32); -void eret(JIT&); -void tlbr(JIT&); -void tlbw(JIT&, int); -void tlbp(JIT&); -} \ No newline at end of file diff --git a/src/backend/core/jit/cop/cop1decode.cpp b/src/backend/core/jit/cop/cop1decode.cpp deleted file mode 100644 index 4b582873..00000000 --- a/src/backend/core/jit/cop/cop1decode.cpp +++ /dev/null @@ -1,464 +0,0 @@ -#include -#include -#include - -namespace n64 { -bool cop1Decode(JIT& cpu, u32 instr) { - Xbyak::CodeGenerator& code = cpu.code; - Registers& regs = cpu.regs; - - u8 mask_sub = (instr >> 21) & 0x1F; - u8 mask_fun = instr & 0x3F; - u8 mask_branch = (instr >> 16) & 0x1F; - - switch(mask_sub) { - // 000r_rccc - case 0x00: - code.mov(code.rax, (u64)mfc1); - code.call(code.rax); - break; - case 0x01: - code.mov(code.rax, (u64)dmfc1); - code.call(code.rax); - break; - case 0x02: - code.mov(code.rax, (u64)cfc1); - code.call(code.rax); - break; - case 0x03: - Util::panic("[RECOMPILER] FPU Reserved instruction exception! {:08X}\n", instr); - case 0x04: - code.mov(code.rax, (u64)mtc1); - code.call(code.rax); - break; - case 0x05: - code.mov(code.rax, (u64)dmtc1); - code.call(code.rax); - break; - case 0x06: - code.mov(code.rax, (u64)ctc1); - code.call(code.rax); - break; - case 0x07: - Util::panic("[RECOMPILER] FPU Reserved instruction exception! {:08X}\n", instr); - case 0x08: - switch(mask_branch) { - case 0: - code.mov(code.rdx, !regs.cop1.fcr31.compare); - code.mov(code.rax, (u64)b); - code.call(code.rax); - return true; - case 1: - code.mov(code.rdx, regs.cop1.fcr31.compare); - code.mov(code.rax, (u64)b); - code.call(code.rax); - return true; - case 2: - code.mov(code.rdx, !regs.cop1.fcr31.compare); - code.mov(code.rax, (u64)bl); - code.call(code.rax); - return true; - case 3: - code.mov(code.rdx, regs.cop1.fcr31.compare); - code.mov(code.rax, (u64)bl); - code.call(code.rax); - return true; - default: Util::panic("Undefined BC COP1 {:02X}\n", mask_branch); - } - break; - case 0x10: // s - switch(mask_fun) { - case 0x00: - code.mov(code.rax, (u64)adds); - code.call(code.rax); - break; - case 0x01: - code.mov(code.rax, (u64)subs); - code.call(code.rax); - break; - case 0x02: - code.mov(code.rax, (u64)muls); - code.call(code.rax); - break; - case 0x03: - code.mov(code.rax, (u64)divs); - code.call(code.rax); - break; - case 0x04: - code.mov(code.rax, (u64)sqrts); - code.call(code.rax); - break; - case 0x05: - code.mov(code.rax, (u64)abss); - code.call(code.rax); - break; - case 0x06: - code.mov(code.rax, (u64)movs); - code.call(code.rax); - break; - case 0x07: - code.mov(code.rax, (u64)negs); - code.call(code.rax); - break; - case 0x08: - code.mov(code.rax, (u64)roundls); - code.call(code.rax); - break; - case 0x09: - code.mov(code.rax, (u64)truncls); - code.call(code.rax); - break; - case 0x0A: - code.mov(code.rax, (u64)ceills); - code.call(code.rax); - break; - case 0x0B: - code.mov(code.rax, (u64)floorls); - code.call(code.rax); - break; - case 0x0C: - code.mov(code.rax, (u64)roundws); - code.call(code.rax); - break; - case 0x0D: - code.mov(code.rax, (u64)truncws); - code.call(code.rax); - break; - case 0x0E: - code.mov(code.rax, (u64)ceilws); - code.call(code.rax); - break; - case 0x0F: - code.mov(code.rax, (u64)floorws); - code.call(code.rax); - break; - case 0x20: - Util::panic("[RECOMPILER] FPU Reserved instruction exception! {:08X}\n", instr); - case 0x21: - code.mov(code.rax, (u64)cvtds); - code.call(code.rax); - break; - case 0x24: - code.mov(code.rax, (u64)cvtws); - code.call(code.rax); - break; - case 0x25: - code.mov(code.rax, (u64)cvtls); - code.call(code.rax); - break; - case 0x30: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, F); - code.call(code.rax); - break; - case 0x31: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, UN); - code.call(code.rax); - break; - case 0x32: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, EQ); - code.call(code.rax); - break; - case 0x33: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, UEQ); - code.call(code.rax); - break; - case 0x34: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, OLT); - code.call(code.rax); - break; - case 0x35: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, ULT); - code.call(code.rax); - break; - case 0x36: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, OLE); - code.call(code.rax); - break; - case 0x37: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, ULE); - code.call(code.rax); - break; - case 0x38: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, SF); - code.call(code.rax); - break; - case 0x39: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, NGLE); - code.call(code.rax); - break; - case 0x3A: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, SEQ); - code.call(code.rax); - break; - case 0x3B: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, NGL); - code.call(code.rax); - break; - case 0x3C: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, LT); - code.call(code.rax); - break; - case 0x3D: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, NGE); - code.call(code.rax); - break; - case 0x3E: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, LE); - code.call(code.rax); - break; - case 0x3F: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, NGT); - code.call(code.rax); - break; - default: Util::panic("Unimplemented COP1 function S[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC); - } - break; - case 0x11: // d - switch(mask_fun) { - case 0x00: - code.mov(code.rax, (u64)addd); - code.call(code.rax); - break; - case 0x01: - code.mov(code.rax, (u64)subd); - code.call(code.rax); - break; - case 0x02: - code.mov(code.rax, (u64)muld); - code.call(code.rax); - break; - case 0x03: - code.mov(code.rax, (u64)divd); - code.call(code.rax); - break; - case 0x04: - code.mov(code.rax, (u64)sqrtd); - code.call(code.rax); - break; - case 0x05: - code.mov(code.rax, (u64)absd); - code.call(code.rax); - break; - case 0x06: - code.mov(code.rax, (u64)movd); - code.call(code.rax); - break; - case 0x07: - code.mov(code.rax, (u64)negd); - code.call(code.rax); - break; - case 0x08: - code.mov(code.rax, (u64)roundld); - code.call(code.rax); - break; - case 0x09: - code.mov(code.rax, (u64)truncld); - code.call(code.rax); - break; - case 0x0A: - code.mov(code.rax, (u64)ceilld); - code.call(code.rax); - break; - case 0x0B: - code.mov(code.rax, (u64)floorld); - code.call(code.rax); - break; - case 0x0C: - code.mov(code.rax, (u64)roundwd); - code.call(code.rax); - break; - case 0x0D: - code.mov(code.rax, (u64)truncwd); - code.call(code.rax); - break; - case 0x0E: - code.mov(code.rax, (u64)ceilwd); - code.call(code.rax); - break; - case 0x0F: - code.mov(code.rax, (u64)floorwd); - code.call(code.rax); - break; - case 0x20: - code.mov(code.rax, (u64)cvtsd); - code.call(code.rax); - break; - case 0x21: - Util::panic("[RECOMPILER] FPU Reserved instruction exception! {:08X}\n", instr); - case 0x24: - code.mov(code.rax, (u64)cvtwd); - code.call(code.rax); - break; - case 0x25: - code.mov(code.rax, (u64)cvtld); - code.call(code.rax); - break; - case 0x30: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, F); - code.call(code.rax); - break; - case 0x31: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, UN); - code.call(code.rax); - break; - case 0x32: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, EQ); - code.call(code.rax); - break; - case 0x33: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, UEQ); - code.call(code.rax); - break; - case 0x34: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, OLT); - code.call(code.rax); - break; - case 0x35: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, ULT); - code.call(code.rax); - break; - case 0x36: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, OLE); - code.call(code.rax); - break; - case 0x37: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, ULE); - code.call(code.rax); - break; - case 0x38: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, SF); - code.call(code.rax); - break; - case 0x39: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, NGLE); - code.call(code.rax); - break; - case 0x3A: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, SEQ); - code.call(code.rax); - break; - case 0x3B: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, NGL); - code.call(code.rax); - break; - case 0x3C: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, LT); - code.call(code.rax); - break; - case 0x3D: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, NGE); - code.call(code.rax); - break; - case 0x3E: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, LE); - code.call(code.rax); - break; - case 0x3F: - code.mov(code.rax, (u64)ccond); - code.mov(code.rdx, NGT); - code.call(code.rax); - break; - default: Util::panic("Unimplemented COP1 function D[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC); - } - break; - case 0x14: // w - switch(mask_fun) { - case 0x01: - code.mov(code.rax, (u64)subw); - code.call(code.rax); - break; - case 0x05: - code.mov(code.rax, (u64)absw); - code.call(code.rax); - break; - case 0x02: - code.mov(code.rax, (u64)mulw); - code.call(code.rax); - break; - case 0x06: - code.mov(code.rax, (u64)movw); - code.call(code.rax); - break; - case 0x20: - code.mov(code.rax, (u64)cvtsw); - code.call(code.rax); - break; - case 0x21: - code.mov(code.rax, (u64)cvtdw); - code.call(code.rax); - break; - case 0x24: - Util::panic("[RECOMPILER] FPU Reserved instruction exception! {:08X}\n", instr); - default: Util::panic("Unimplemented COP1 function W[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC); - } - break; - case 0x15: // l - switch(mask_fun) { - case 0x01: - code.mov(code.rax, (u64)subl); - code.call(code.rax); - break; - case 0x05: - code.mov(code.rax, (u64)absl); - code.call(code.rax); - break; - case 0x02: - code.mov(code.rax, (u64)mull); - code.call(code.rax); - break; - case 0x06: - code.mov(code.rax, (u64)movl); - code.call(code.rax); - break; - case 0x20: - code.mov(code.rax, (u64)cvtsl); - code.call(code.rax); - break; - case 0x21: - code.mov(code.rax, (u64)cvtdl); - code.call(code.rax); - break; - case 0x24: - Util::panic("[RECOMPILER] FPU Reserved instruction exception! {:08X}\n", instr); - case 0x25: - Util::panic("[RECOMPILER] FPU Reserved instruction exception! {:08X}\n", instr); - default: Util::panic("Unimplemented COP1 function L[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC); - } - break; - default: Util::panic("Unimplemented COP1 instruction {} {}", mask_sub >> 3, mask_sub & 7); - } - - return false; -} -} \ No newline at end of file diff --git a/src/backend/core/jit/cop/cop1decode.hpp b/src/backend/core/jit/cop/cop1decode.hpp deleted file mode 100644 index 2aab3e56..00000000 --- a/src/backend/core/jit/cop/cop1decode.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#include - -namespace n64 { -bool cop1Decode(JIT& cpu, u32 instr); -} \ No newline at end of file diff --git a/src/backend/core/jit/cop/cop1instructions.cpp b/src/backend/core/jit/cop/cop1instructions.cpp deleted file mode 100644 index d5090d35..00000000 --- a/src/backend/core/jit/cop/cop1instructions.cpp +++ /dev/null @@ -1,617 +0,0 @@ -#include -#include -#include -#include -#include - -namespace n64 { -inline int PushRoundingMode(const FCR31& fcr31) { - int og = fegetround(); - switch(fcr31.rounding_mode) { - case 0: fesetround(FE_TONEAREST); break; - case 1: fesetround(FE_TOWARDZERO); break; - case 2: fesetround(FE_UPWARD); break; - case 3: fesetround(FE_DOWNWARD); break; - } - - return og; -} - -#define PUSHROUNDINGMODE int og = PushRoundingMode(regs.cop1.fcr31) -#define POPROUNDINGMODE fesetround(og) - -#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; \ - } \ -} while(0) - -void absd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), std::abs(fs)); -} - -void abss(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), std::abs(fs)); -} - -void absw(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s32 fs = regs.cop1.GetReg(regs.cop0, FS(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), std::abs(fs)); -} - -void absl(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s64 fs = regs.cop1.GetReg(regs.cop0, FS(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), std::abs(fs)); -} - -void adds(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - float ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); - checknanregs(fs, ft); - float result = fs + ft; - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), result); -} - -void addd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - double ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); - checknanregs(fs, ft); - double result = fs + ft; - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), result); -} - -void ceills(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s64 result = std::ceil(fs); - regs.cop1.SetReg(regs.cop0, FD(instr), result); -} - -void ceilws(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s32 result = std::ceil(fs); - regs.cop1.SetReg(regs.cop0, FD(instr), result); -} - -void ceilld(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s64 result = std::ceil(fs); - regs.cop1.SetReg(regs.cop0, FD(instr), result); -} - -void ceilwd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s32 result = std::ceil(fs); - regs.cop1.SetReg(regs.cop0, FD(instr), result); -} - -void cfc1(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - u8 fd = RD(instr); - s32 val = 0; - switch(fd) { - case 0: val = regs.cop1.fcr0; break; - case 31: - val = regs.cop1.fcr31.raw; - break; - default: Util::panic("Undefined CFC1 with rd != 0 or 31\n"); - } - regs.gpr[RT(instr)] = val; -} - -void ctc1(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - u8 fs = RD(instr); - u32 val = regs.gpr[RT(instr)]; - switch(fs) { - case 0: break; - case 31: { - val &= 0x183ffff; - regs.cop1.fcr31.raw = val; - } break; - default: Util::panic("Undefined CTC1 with rd != 0 or 31\n"); - } -} - -void cvtds(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetCop1Reg( - regs.cop0, - FD(instr), - regs.cop1.GetCop1Reg( - regs.cop0, - FS(instr) - ) - ); -} - -void cvtsd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetCop1Reg( - regs.cop0, - FD(instr), - regs.cop1.GetCop1Reg( - regs.cop0, - FS(instr) - ) - ); -} - -void cvtwd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetReg( - regs.cop0, - FD(instr), - regs.cop1.GetCop1Reg( - regs.cop0, - FS(instr) - ) - ); -} - -void cvtws(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetReg( - regs.cop0, - FD(instr), - regs.cop1.GetCop1Reg( - regs.cop0, - FS(instr) - ) - ); -} - -void cvtls(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetReg( - regs.cop0, - FD(instr), - regs.cop1.GetCop1Reg( - regs.cop0, - FS(instr) - ) - ); -} - -void cvtsl(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetCop1Reg( - regs.cop0, - FD(instr), - (s64)regs.cop1.GetReg( - regs.cop0, - FS(instr) - ) - ); -} - -void cvtdw(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetCop1Reg( - regs.cop0, - FD(instr), - (s32)regs.cop1.GetReg( - regs.cop0, - FS(instr) - ) - ); -} - -void cvtsw(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetCop1Reg( - regs.cop0, - FD(instr), - (s32)regs.cop1.GetReg( - regs.cop0, - FS(instr) - ) - ); -} - -void cvtdl(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetCop1Reg( - regs.cop0, - FD(instr), - (s64)regs.cop1.GetReg( - regs.cop0, - FS(instr) - ) - ); -} - -void cvtld(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetReg( - regs.cop0, - FD(instr), - regs.cop1.GetCop1Reg( - regs.cop0, - FS(instr) - ) - ); -} - -template -inline bool CalculateCondition(Registers& regs, T fs, T ft, CompConds cond) { - switch(cond) { - case F: return false; - case UN: return std::isnan(fs) || std::isnan(ft); - case EQ: return fs == ft; - case UEQ: return (std::isnan(fs) || std::isnan(ft)) || (fs == ft); - case OLT: return (!std::isnan(fs) && !std::isnan(ft)) && (fs < ft); - case ULT: return (std::isnan(fs) || std::isnan(ft)) || (fs < ft); - case OLE: return (!std::isnan(fs) && !std::isnan(ft)) && (fs <= ft); - case ULE: return (std::isnan(fs) || std::isnan(ft)) || (fs <= ft); - default: - 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 false; - } - - return CalculateCondition(regs, fs, ft, static_cast(cond - 8)); - } -} - -template -void ccond(JIT& dyn, u32 instr, CompConds cond) { - Registers& regs = dyn.regs; - T fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - T ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); - - regs.cop1.fcr31.compare = CalculateCondition(regs, fs, ft, cond); -} - -template void ccond(JIT& dyn, u32 instr, CompConds cond); -template void ccond(JIT& dyn, u32 instr, CompConds cond); - -void divs(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - float ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), fs / ft); -} - -void divd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - double ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), fs / ft); -} - -void muls(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - float ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), fs * ft); -} - -void muld(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - double ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), fs * ft); -} - -void mulw(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - u32 fs = regs.cop1.GetReg(regs.cop0, FS(instr)); - u32 ft = regs.cop1.GetReg(regs.cop0, FT(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), fs * ft); -} - -void mull(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - u64 fs = regs.cop1.GetReg(regs.cop0, FS(instr)); - u64 ft = regs.cop1.GetReg(regs.cop0, FT(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), fs * ft); -} - -void subs(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - float ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), fs - ft); -} - -void subd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - double ft = regs.cop1.GetCop1Reg(regs.cop0, FT(instr)); - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), fs - ft); -} - -void subw(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - u32 fs = regs.cop1.GetReg(regs.cop0, FS(instr)); - u32 ft = regs.cop1.GetReg(regs.cop0, FT(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), fs - ft); -} - -void subl(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - u64 fs = regs.cop1.GetReg(regs.cop0, FS(instr)); - u64 ft = regs.cop1.GetReg(regs.cop0, FT(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), fs - ft); -} - -void movs(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetCop1Reg( - regs.cop0, - FD(instr), - regs.cop1.GetCop1Reg( - regs.cop0, - FS(instr) - ) - ); -} - -void movd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetCop1Reg( - regs.cop0, - FD(instr), - regs.cop1.GetCop1Reg( - regs.cop0, - FS(instr) - ) - ); -} - -void movw(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetReg( - regs.cop0, - FD(instr), - regs.cop1.GetReg( - regs.cop0, - FS(instr) - ) - ); -} - -void movl(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetReg( - regs.cop0, - FD(instr), - regs.cop1.GetReg( - regs.cop0, - FS(instr) - ) - ); -} - -void negs(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetCop1Reg( - regs.cop0, - FD(instr), - -regs.cop1.GetCop1Reg( - regs.cop0, - FS(instr) - ) - ); -} - -void negd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetCop1Reg( - regs.cop0, - FD(instr), - -regs.cop1.GetCop1Reg( - regs.cop0, - FS(instr) - ) - ); -} - -void sqrts(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), std::sqrt(fs)); -} - -void sqrtd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetCop1Reg(regs.cop0, FD(instr), std::sqrt(fs)); -} - -void roundls(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - PUSHROUNDINGMODE; - regs.cop1.SetReg(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); - POPROUNDINGMODE; -} - -void roundld(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - PUSHROUNDINGMODE; - regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::nearbyint(fs)); - POPROUNDINGMODE; -} - -void roundws(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - PUSHROUNDINGMODE; - regs.cop1.SetReg(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); - POPROUNDINGMODE; -} - -void roundwd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - PUSHROUNDINGMODE; - regs.cop1.SetReg(regs.cop0, FD(instr), (s32)std::nearbyint(fs)); - POPROUNDINGMODE; -} - -void floorls(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); -} - -void floorld(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); -} - -void floorws(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); -} - -void floorwd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - regs.cop1.SetReg(regs.cop0, FD(instr), (s64)std::floor(fs)); -} - -void lwc1(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(!regs.cop0.status.cu1) { - FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true); - return; - } - - u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)]; - - u32 physical; - if(!MapVAddr(regs, LOAD, addr, physical)) { - HandleTLBException(regs, addr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - u32 data = dyn.mem.Read32(regs, physical); - regs.cop1.SetReg(regs.cop0, FT(instr), data); - } -} - -void swc1(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(!regs.cop0.status.cu1) { - FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true); - return; - } - - u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)]; - - u32 physical; - if(!MapVAddr(regs, STORE, addr, physical)) { - HandleTLBException(regs, addr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); - } else { - dyn.mem.Write32(regs, physical, regs.cop1.GetReg(regs.cop0, FT(instr))); - } -} - -void ldc1(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(!regs.cop0.status.cu1) { - FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true); - return; - } - - u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)]; - - u32 physical; - if(!MapVAddr(regs, LOAD, addr, physical)) { - HandleTLBException(regs, addr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - u64 data = dyn.mem.Read64(regs, physical); - regs.cop1.SetReg(regs.cop0, FT(instr), data); - } -} - -void sdc1(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(!regs.cop0.status.cu1) { - FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true); - return; - } - - u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)]; - - u32 physical; - if(!MapVAddr(regs, STORE, addr, physical)) { - HandleTLBException(regs, addr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); - } else { - dyn.mem.Write64(regs, physical, regs.cop1.GetReg(regs.cop0, FT(instr))); - } -} - -void truncws(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s32 result = (s32)std::trunc(fs); - regs.cop1.SetReg(regs.cop0, FD(instr), result); -} - -void truncwd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s32 result = (s32)std::trunc(fs); - regs.cop1.SetReg(regs.cop0, FD(instr), result); -} - -void truncls(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - float fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s64 result = (s64)std::trunc(fs); - regs.cop1.SetReg(regs.cop0, FD(instr), result); -} - -void truncld(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - double fs = regs.cop1.GetCop1Reg(regs.cop0, FS(instr)); - s64 result = (s64)std::trunc(fs); - regs.cop1.SetReg(regs.cop0, FD(instr), result); -} - -void mfc1(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.gpr[RT(instr)] = (s32)regs.cop1.GetReg(regs.cop0, FS(instr)); -} - -void dmfc1(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.gpr[RT(instr)] = (s64)regs.cop1.GetReg(regs.cop0, FS(instr)); -} - -void mtc1(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetReg(regs.cop0, FS(instr), regs.gpr[RT(instr)]); -} - -void dmtc1(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.cop1.SetReg(regs.cop0, FS(instr), regs.gpr[RT(instr)]); -} - -} \ No newline at end of file diff --git a/src/backend/core/jit/cop/cop1instructions.hpp b/src/backend/core/jit/cop/cop1instructions.hpp deleted file mode 100644 index 2424b20c..00000000 --- a/src/backend/core/jit/cop/cop1instructions.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once -#include -#include - -namespace n64 { -void absd(JIT&, u32 instr); -void abss(JIT&, u32 instr); -void absw(JIT&, u32 instr); -void absl(JIT&, u32 instr); -void adds(JIT&, u32 instr); -void addd(JIT&, u32 instr); -void subs(JIT&, u32 instr); -void subd(JIT&, u32 instr); -void subw(JIT&, u32 instr); -void subl(JIT&, u32 instr); -void ceills(JIT&, u32 instr); -void ceilws(JIT&, u32 instr); -void ceilld(JIT&, u32 instr); -void ceilwd(JIT&, u32 instr); -void cfc1(JIT&, u32 instr); -void ctc1(JIT&, u32 instr); -void roundls(JIT&, u32 instr); -void roundld(JIT&, u32 instr); -void roundws(JIT&, u32 instr); -void roundwd(JIT&, u32 instr); -void floorls(JIT&, u32 instr); -void floorld(JIT&, u32 instr); -void floorws(JIT&, u32 instr); -void floorwd(JIT&, u32 instr); -void cvtls(JIT&, u32 instr); -void cvtws(JIT&, u32 instr); -void cvtds(JIT&, u32 instr); -void cvtsw(JIT&, u32 instr); -void cvtdw(JIT&, u32 instr); -void cvtsd(JIT&, u32 instr); -void cvtwd(JIT&, u32 instr); -void cvtld(JIT&, u32 instr); -void cvtdl(JIT&, u32 instr); -void cvtsl(JIT&, u32 instr); -template -void ccond(JIT&, u32 instr, CompConds); -void divs(JIT&, u32 instr); -void divd(JIT&, u32 instr); -void muls(JIT&, u32 instr); -void muld(JIT&, u32 instr); -void mulw(JIT&, u32 instr); -void mull(JIT&, u32 instr); -void movs(JIT&, u32 instr); -void movd(JIT&, u32 instr); -void movw(JIT&, u32 instr); -void movl(JIT&, u32 instr); -void negs(JIT&, u32 instr); -void negd(JIT&, u32 instr); -void sqrts(JIT&, u32 instr); -void sqrtd(JIT&, u32 instr); -void lwc1(JIT&, u32 instr); -void swc1(JIT&, u32 instr); -void ldc1(JIT&, u32 instr); -void mfc1(JIT&, u32 instr); -void dmfc1(JIT&, u32 instr); -void mtc1(JIT&, u32 instr); -void dmtc1(JIT&, u32 instr); -void sdc1(JIT&, u32 instr); -void truncws(JIT&, u32 instr); -void truncwd(JIT&, u32 instr); -void truncls(JIT&, u32 instr); -void truncld(JIT&, u32 instr); -} \ No newline at end of file diff --git a/src/backend/core/jit/decode.cpp b/src/backend/core/jit/decode.cpp deleted file mode 100644 index 1b909f27..00000000 --- a/src/backend/core/jit/decode.cpp +++ /dev/null @@ -1,655 +0,0 @@ -#include -#include -#include -#include - -namespace n64 { -void JIT::cop2Decode(u32 instr) { - switch(RS(instr)) { - case 0x00: - code.mov(rax, (u64)mfc2); - code.call(rax); - break; - case 0x01: - code.mov(rax, (u64)dmfc2); - code.call(rax); - break; - case 0x02: case 0x06: break; - case 0x04: - code.mov(rax, (u64)mtc2); - code.call(rax); - break; - case 0x05: - code.mov(rax, (u64)dmtc2); - code.call(rax); - break; - default: - Util::panic("[RECOMPILER] Unhandled reserved instruction exception {:016X}\n", (u64)regs.pc); - } -} - -bool JIT::special(u32 instr) { - u8 mask = (instr & 0x3F); - bool res = false; - - // 00rr_rccc - switch (mask) { // TODO: named constants for clearer code - case 0: - if (instr != 0) { - code.mov(rax, (u64)sll); - code.call(rax); - } - break; - case 0x02: - code.mov(rax, (u64)srl); - code.call(rax); - break; - case 0x03: - code.mov(rax, (u64)sra); - code.call(rax); - break; - case 0x04: - code.mov(rax, (u64)sllv); - code.call(rax); - break; - case 0x06: - code.mov(rax, (u64)srlv); - code.call(rax); - break; - case 0x07: - code.mov(rax, (u64)srav); - code.call(rax); - break; - case 0x08: - code.mov(rax, (u64)jr); - code.call(rax); - res = true; - break; - case 0x09: - code.mov(rax, (u64)jalr); - code.call(rax); - res = true; - break; - case 0x0C: Util::panic("[RECOMPILER] Unhandled syscall instruction {:016X}\n", (u64)regs.pc); - case 0x0D: Util::panic("[RECOMPILER] Unhandled break instruction {:016X}\n", (u64)regs.pc); - case 0x0F: break; // SYNC - case 0x10: - code.mov(rax, (u64)mfhi); - code.call(rax); - break; - case 0x11: - code.mov(rax, (u64)mthi); - code.call(rax); - break; - case 0x12: - code.mov(rax, (u64)mflo); - code.call(rax); - break; - case 0x13: - code.mov(rax, (u64)mtlo); - code.call(rax); - break; - case 0x14: - code.mov(rax, (u64)dsllv); - code.call(rax); - break; - case 0x16: - code.mov(rax, (u64)dsrlv); - code.call(rax); - break; - case 0x17: - code.mov(rax, (u64)dsrav); - code.call(rax); - break; - case 0x18: - code.mov(rax, (u64)mult); - code.call(rax); - break; - case 0x19: - code.mov(rax, (u64)multu); - code.call(rax); - break; - case 0x1A: - code.mov(rax, (u64)div); - code.call(rax); - break; - case 0x1B: - code.mov(rax, (u64)divu); - code.call(rax); - break; - case 0x1C: - code.mov(rax, (u64)dmult); - code.call(rax); - break; - case 0x1D: - code.mov(rax, (u64)dmultu); - code.call(rax); - break; - case 0x1E: - code.mov(rax, (u64)ddiv); - code.call(rax); - break; - case 0x1F: - code.mov(rax, (u64)ddivu); - code.call(rax); - break; - case 0x20: - code.mov(rax, (u64)add); - code.call(rax); - break; - case 0x21: - code.mov(rax, (u64)addu); - code.call(rax); - break; - case 0x22: - code.mov(rax, (u64)sub); - code.call(rax); - break; - case 0x23: - code.mov(rax, (u64)subu); - code.call(rax); - break; - case 0x24: - code.mov(rax, (u64)and_); - code.call(rax); - break; - case 0x25: - code.mov(rax, (u64)or_); - code.call(rax); - break; - case 0x26: - code.mov(rax, (u64)xor_); - code.call(rax); - break; - case 0x27: - code.mov(rax, (u64)nor); - code.call(rax); - break; - case 0x2A: - code.mov(rax, (u64)slt); - code.call(rax); - break; - case 0x2B: - code.mov(rax, (u64)sltu); - code.call(rax); - break; - case 0x2C: - code.mov(rax, (u64)dadd); - code.call(rax); - break; - case 0x2D: - code.mov(rax, (u64)daddu); - code.call(rax); - break; - case 0x2E: - code.mov(rax, (u64)dsub); - code.call(rax); - break; - case 0x2F: - code.mov(rax, (u64)dsubu); - code.call(rax); - break; - case 0x30: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); - code.xor_(rsi, rsi); - code.cmp(r8, rcx); - code.setge(sil); - code.mov(rax, (u64)trap); - code.call(rax); - res = true; - break; - case 0x31: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); - code.xor_(rsi, rsi); - code.cmp(r8, rcx); - code.setae(sil); - code.mov(rax, (u64)trap); - code.call(rax); - res = true; - break; - case 0x32: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); - code.xor_(rsi, rsi); - code.cmp(r8, rcx); - code.setl(sil); - code.mov(rax, (u64)trap); - code.call(rax); - res = true; - break; - case 0x33: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); - code.xor_(rsi, rsi); - code.cmp(r8, rcx); - code.setb(sil); - code.mov(rax, (u64)trap); - code.call(rax); - res = true; - break; - case 0x34: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); - code.xor_(rsi, rsi); - code.cmp(r8, rcx); - code.sete(sil); - code.mov(rax, (u64)trap); - code.call(rax); - res = true; - break; - case 0x36: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); - code.xor_(rsi, rsi); - code.cmp(r8, rcx); - code.setne(sil); - code.mov(rax, (u64)trap); - code.call(rax); - res = true; - break; - case 0x38: - code.mov(rax, (u64)dsll); - code.call(rax); - break; - case 0x3A: - code.mov(rax, (u64)dsrl); - code.call(rax); - break; - case 0x3B: - code.mov(rax, (u64)dsra); - code.call(rax); - break; - case 0x3C: - code.mov(rax, (u64)dsll32); - code.call(rax); - break; - case 0x3E: - code.mov(rax, (u64)dsrl32); - code.call(rax); - break; - case 0x3F: - code.mov(rax, (u64)dsra32); - code.call(rax); - break; - default: - Util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 7, mask & 7, instr, (u64)regs.oldPC); - } - - return res; -} - -bool JIT::regimm(u32 instr) { - u8 mask = ((instr >> 16) & 0x1F); - // 000r_rccc - switch (mask) { // TODO: named constants for clearer code - case 0x00: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rdx, rdx); - code.cmp(r8, 0); - code.setl(dl); - code.mov(rax, (u64)b); - code.call(rax); - break; - case 0x01: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rdx, rdx); - code.cmp(r8, 0); - code.setge(dl); - code.mov(rax, (u64)b); - code.call(rax); - break; - case 0x02: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rdx, rdx); - code.cmp(r8, 0); - code.setl(dl); - code.mov(rax, (u64)bl); - code.call(rax); - break; - case 0x03: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rdx, rdx); - code.cmp(r8, 0); - code.setge(dl); - code.mov(rax, (u64)bl); - code.call(rax); - break; - case 0x08: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rsi, rsi); - code.cmp(r8, s64(s16(instr))); - code.setge(sil); - code.mov(rax, (u64)trap); - code.call(rax); - break; - case 0x09: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rsi, rsi); - code.cmp(r8, u64(s64(s16(instr)))); - code.setae(sil); - code.mov(rax, (u64)trap); - code.call(rax); - break; - case 0x0A: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rsi, rsi); - code.cmp(r8, s64(s16(instr))); - code.setl(sil); - code.mov(rax, (u64)trap); - code.call(rax); - break; - case 0x0B: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rsi, rsi); - code.cmp(r8, u64(s64(s16(instr)))); - code.setb(sil); - code.mov(rax, (u64)trap); - code.call(rax); - break; - case 0x0C: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rsi, rsi); - code.cmp(r8, s64(s16(instr))); - code.sete(sil); - code.mov(rax, (u64)trap); - code.call(rax); - break; - case 0x0E: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rsi, rsi); - code.cmp(r8, s64(s16(instr))); - code.setne(sil); - code.mov(rax, (u64)trap); - code.call(rax); - break; - case 0x10: - code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rdx, rdx); - code.cmp(rcx, 0); - code.setl(dl); - code.mov(rax, (u64)blink); - code.call(rax); - break; - case 0x11: - code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rdx, rdx); - code.cmp(rcx, 0); - code.setge(dl); - code.mov(rax, (u64)blink); - code.call(rax); - break; - case 0x12: - code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rdx, rdx); - code.cmp(rcx, 0); - code.setl(dl); - code.mov(rax, (u64)bllink); - code.call(rax); - break; - case 0x13: - code.mov(rcx, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rdx, rdx); - code.cmp(rcx, 0); - code.setge(dl); - code.mov(rax, (u64)bllink); - code.call(rax); - break; - default: - Util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})\n", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC); - } - - return true; -} - -bool JIT::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(instr); break; - case 0x01: res = regimm(instr); break; - case 0x02: - code.mov(rax, (u64)j); - code.call(rax); - res = true; - break; - case 0x03: - code.mov(rax, (u64)jal); - code.call(rax); - res = true; - break; - case 0x04: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.mov(r9, qword[rdi + GPR_OFFSET(RT(instr), this)]); - code.xor_(rdx, rdx); - code.cmp(r8, r9); - code.sete(dl); - code.mov(rax, (u64)b); - code.call(rax); - res = true; - break; - case 0x05: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.mov(r9, qword[rdi + GPR_OFFSET(RT(instr), this)]); - code.xor_(rdx, rdx); - code.cmp(r8, r9); - code.setne(dl); - code.mov(rax, (u64)b); - code.call(rax); - res = true; - break; - case 0x06: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rdx, rdx); - code.test(r8, r8); - code.setnz(dl); - code.mov(rax, (u64)b); - code.call(rax); - res = true; - break; - case 0x07: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rdx, rdx); - code.test(r8, r8); - code.setg(dl); - code.mov(rax, (u64)b); - code.call(rax); - res = true; - break; - case 0x08: - code.mov(rax, (u64)addi); - code.call(rax); - break; - case 0x09: - code.mov(rax, (u64)addiu); - code.call(rax); - break; - case 0x0A: - code.mov(rax, (u64)slti); - code.call(rax); - break; - case 0x0B: - code.mov(rax, (u64)sltiu); - code.call(rax); - break; - case 0x0C: - code.mov(rax, (u64)andi); - code.call(rax); - break; - case 0x0D: - code.mov(rax, (u64)ori); - code.call(rax); - break; - case 0x0E: - code.mov(rax, (u64)xori); - code.call(rax); - break; - case 0x0F: - code.mov(rax, (u64)lui); - code.call(rax); - break; - case 0x10: cop0Decode(*this, instr); break; - case 0x11: res = cop1Decode(*this, instr); break; - case 0x12: cop2Decode(instr); break; - case 0x14: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); - code.xor_(rdx, rdx); - code.cmp(r8, rcx); - code.sete(dl); - code.mov(rax, (u64)bl); - code.call(rax); - break; - case 0x15: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.mov(rcx, qword[rdi + GPR_OFFSET(RT(instr), this)]); - code.xor_(rdx, rdx); - code.cmp(r8, rcx); - code.setne(dl); - code.mov(rax, (u64)bl); - code.call(rax); - break; - case 0x16: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rdx, rdx); - code.cmp(r8, 0); - code.setle(dl); - code.mov(rax, (u64)bl); - code.call(rax); - break; - case 0x17: - code.mov(r8, qword[rdi + GPR_OFFSET(RS(instr), this)]); - code.xor_(rdx, rdx); - code.cmp(r8, 0); - code.setg(dl); - code.mov(rax, (u64)b); - code.call(rax); - break; - case 0x18: - code.mov(rax, (u64)daddi); - code.call(rax); - break; - case 0x19: - code.mov(rax, (u64)daddiu); - code.call(rax); - break; - case 0x1A: - code.mov(rax, (u64)ldl); - code.call(rax); - break; - case 0x1B: - 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(rax, (u64)lb); - code.call(rax); - break; - case 0x21: - code.mov(rax, (u64)lh); - code.call(rax); - break; - case 0x22: - code.mov(rax, (u64)lwl); - code.call(rax); - break; - case 0x23: - code.mov(rax, (u64)lw); - code.call(rax); - break; - case 0x24: - code.mov(rax, (u64)lbu); - code.call(rax); - break; - case 0x25: - code.mov(rax, (u64)lhu); - code.call(rax); - break; - case 0x26: - code.mov(rax, (u64)lwr); - code.call(rax); - break; - case 0x27: - code.mov(rax, (u64)lwu); - code.call(rax); - break; - case 0x28: - code.mov(rax, (u64)sb); - code.call(rax); - break; - case 0x29: - code.mov(rax, (u64)sh); - code.call(rax); - break; - case 0x2A: - code.mov(rax, (u64)swl); - code.call(rax); - break; - case 0x2B: - code.mov(rax, (u64)sw); - code.call(rax); - break; - case 0x2C: - code.mov(rax, (u64)sdl); - code.call(rax); - break; - case 0x2D: - code.mov(rax, (u64)sdr); - code.call(rax); - break; - case 0x2E: - code.mov(rax, (u64)swr); - code.call(rax); - break; - case 0x2F: break; // CACHE - case 0x30: - code.mov(rax, (u64)ll); - code.call(rax); - break; - case 0x31: - code.mov(rax, (u64)lwc1); - code.call(rax); - break; - case 0x34: - code.mov(rax, (u64)lld); - code.call(rax); - break; - case 0x35: - code.mov(rax, (u64)ldc1); - code.call(rax); - break; - case 0x37: - code.mov(rax, (u64)ld); - code.call(rax); - break; - case 0x38: - code.mov(rax, (u64)sc); - code.call(rax); - break; - case 0x39: - code.mov(rax, (u64)swc1); - code.call(rax); - break; - case 0x3C: - code.mov(rax, (u64)scd); - code.call(rax); - break; - case 0x3D: - code.mov(rax, (u64)sdc1); - code.call(rax); - break; - case 0x3F: - code.mov(rax, (u64)sd); - code.call(rax); - break; - default: - Util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})\n", mask, instr, (u64)regs.oldPC); - } - - return res; -} -} diff --git a/src/backend/core/jit/instructions.cpp b/src/backend/core/jit/instructions.cpp deleted file mode 100644 index 0132cdb6..00000000 --- a/src/backend/core/jit/instructions.cpp +++ /dev/null @@ -1,1051 +0,0 @@ -#include - -#define check_address_error(mask, vaddr) (((!regs.cop0.is_64bit_addressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0)) -#define check_signed_overflow(op1, op2, res) (((~((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1) -#define check_signed_underflow(op1, op2, res) (((((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1) - -namespace n64 { -void add(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - u32 rs = (s32)regs.gpr[RS(instr)]; - u32 rt = (s32)regs.gpr[RT(instr)]; - u32 result = rs + rt; - - Util::debug("add r{}, r{}, r{} = {:08X}\n", RD(instr), RS(instr), RT(instr), result); - - if(check_signed_overflow(rs, rt, result)) { - FireException(regs, ExceptionCode::Overflow, 0, true); - } else { - if(likely(RD(instr) != 0)) { - regs.gpr[RD(instr)] = s32(result); - } - } -} - -void addu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - s32 rs = (s32)regs.gpr[RS(instr)]; - s32 rt = (s32)regs.gpr[RT(instr)]; - s32 result = rs + rt; - regs.gpr[RD(instr)] = result; - Util::debug("addu r{}, r{}, r{} = {:08X}\n", RD(instr), RS(instr), RT(instr), (u32)result); - } -} - -void addi(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - u32 rs = regs.gpr[RS(instr)]; - u32 imm = s32(s16(instr)); - u32 result = rs + imm; - Util::debug("addi r{}, r{}, {:08X} = {:08X}\n", RT(instr), RS(instr), imm, result); - if(check_signed_overflow(rs, imm, result)) { - FireException(regs, ExceptionCode::Overflow, 0, true); - } else { - regs.gpr[RT(instr)] = s32(result); - } -} - -void addiu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s32 rs = (s32)regs.gpr[RS(instr)]; - s16 imm = (s16)(instr); - s32 result = rs + imm; - regs.gpr[RT(instr)] = result; -} - -void dadd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - u64 rs = regs.gpr[RS(instr)]; - u64 rt = regs.gpr[RT(instr)]; - u64 result = rt + rs; - if(check_signed_overflow(rs, rt, result)) { - FireException(regs, ExceptionCode::Overflow, 0, true); - } else { - if(likely(RD(instr) != 0)) { - regs.gpr[RD(instr)] = result; - } - } -} - -void daddu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - s64 rs = regs.gpr[RS(instr)]; - s64 rt = regs.gpr[RT(instr)]; - regs.gpr[RD(instr)] = rs + rt; - } -} - -void daddi(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - u64 imm = s64(s16(instr)); - u64 rs = regs.gpr[RS(instr)]; - u64 result = imm + rs; - if(check_signed_overflow(rs, imm, result)) { - FireException(regs, ExceptionCode::Overflow, 0, true); - } else { - regs.gpr[RT(instr)] = result; - } -} - -void daddiu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s16 imm = (s16)(instr); - s64 rs = regs.gpr[RS(instr)]; - regs.gpr[RT(instr)] = rs + imm; -} - -void div(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s64 dividend = (s32)regs.gpr[RS(instr)]; - s64 divisor = (s32)regs.gpr[RT(instr)]; - - if(divisor == 0) { - regs.hi = dividend; - if(dividend >= 0) { - regs.lo = s64(-1); - } else { - regs.lo = s64(1); - } - } else { - s32 quotient = dividend / divisor; - s32 remainder = dividend % divisor; - regs.lo = quotient; - regs.hi = remainder; - } -} - -void divu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - u32 dividend = regs.gpr[RS(instr)]; - u32 divisor = regs.gpr[RT(instr)]; - if(divisor == 0) { - regs.lo = -1; - regs.hi = (s32)dividend; - } else { - s32 quotient = (s32)(dividend / divisor); - s32 remainder = (s32)(dividend % divisor); - regs.lo = quotient; - regs.hi = remainder; - } -} - -void ddiv(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s64 dividend = regs.gpr[RS(instr)]; - s64 divisor = regs.gpr[RT(instr)]; - if (dividend == 0x8000000000000000 && divisor == 0xFFFFFFFFFFFFFFFF) { - regs.lo = dividend; - regs.hi = 0; - } else if(divisor == 0) { - regs.hi = dividend; - if(dividend >= 0) { - regs.lo = -1; - } else { - regs.lo = 1; - } - } else { - s64 quotient = dividend / divisor; - s64 remainder = dividend % divisor; - regs.lo = quotient; - regs.hi = remainder; - } -} - -void ddivu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - u64 dividend = regs.gpr[RS(instr)]; - u64 divisor = regs.gpr[RT(instr)]; - if(divisor == 0) { - regs.lo = -1; - regs.hi = (s64)dividend; - } else { - u64 quotient = dividend / divisor; - u64 remainder = dividend % divisor; - regs.lo = (s64)quotient; - regs.hi = (s64)remainder; - } -} - -void branch(JIT& dyn, bool cond, s64 address) { - Registers& regs = dyn.regs; - regs.delaySlot = true; - if (cond) { - regs.nextPC = address; - } -} - -void branch_likely(JIT& dyn, bool cond, s64 address) { - Registers& regs = dyn.regs; - if (cond) { - regs.delaySlot = true; - regs.nextPC = address; - } else { - regs.SetPC64(regs.nextPC); - } -} - -void b(JIT& dyn, u32 instr, bool cond) { - Registers& regs = dyn.regs; - s16 imm = instr; - s64 offset = (s64)imm << 2; - s64 address = regs.pc + offset; - branch(dyn, cond, address); -} - -void blink(JIT& dyn, u32 instr, bool cond) { - Registers& regs = dyn.regs; - regs.gpr[31] = regs.nextPC; - s16 imm = instr; - s64 offset = (s64)imm << 2; - s64 address = regs.pc + offset; - branch(dyn, cond, address); -} - -void bl(JIT& dyn, u32 instr, bool cond) { - Registers& regs = dyn.regs; - s16 imm = instr; - s64 offset = (s64)imm << 2; - s64 address = regs.pc + offset; - branch_likely(dyn, cond, address); -} - -void bllink(JIT& dyn, u32 instr, bool cond) { - Registers& regs = dyn.regs; - regs.gpr[31] = regs.nextPC; - s16 imm = instr; - s64 offset = (s64)imm << 2; - s64 address = regs.pc + offset; - branch_likely(dyn, cond, address); -} - -void lui(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s64 val = (s16)instr; - val <<= 16; - regs.gpr[RT(instr)] = val; -} - -void lb(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - u64 address = regs.gpr[RS(instr)] + (s16)instr; - u32 paddr = 0; - if(!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - regs.gpr[RT(instr)] = (s8)mem.Read8(regs, paddr); - } -} - -void lh(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - u64 address = regs.gpr[RS(instr)] + (s16)instr; - if ((address & 0b1) > 0) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); - return; - } - - u32 paddr = 0; - if(!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - regs.gpr[RT(instr)] = (s16)mem.Read16(regs, paddr); - } -} - -void lw(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - s16 offset = instr; - u64 address = regs.gpr[RS(instr)] + offset; - if (check_address_error(0b11, address)) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); - return; - } - - u32 physical = 0; - if (!MapVAddr(regs, LOAD, address, physical)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - regs.gpr[RT(instr)] = (s32)mem.Read32(regs, physical); - } -} - -void ll(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - u64 address = regs.gpr[RS(instr)] + (s16)instr; - u32 physical; - if (!MapVAddr(regs, LOAD, address, physical)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - if ((address & 0b11) > 0) { - FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); - return; - } else { - regs.gpr[RT(instr)] = (s32)mem.Read32(regs, physical); - } - } - - regs.cop0.llbit = true; - regs.cop0.LLAddr = physical >> 4; -} - -void lwl(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - u64 address = regs.gpr[RS(instr)] + (s16)instr; - u32 paddr = 0; - if(!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - u32 shift = 8 * ((address ^ 0) & 3); - u32 mask = 0xFFFFFFFF << shift; - u32 data = mem.Read32(regs, paddr & ~3); - s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data << shift)); - regs.gpr[RT(instr)] = result; - } -} - -void lwr(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - u64 address = regs.gpr[RS(instr)] + (s16)instr; - u32 paddr = 0; - if(!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - u32 shift = 8 * ((address ^ 3) & 3); - u32 mask = 0xFFFFFFFF >> shift; - u32 data = mem.Read32(regs, paddr & ~3); - s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data >> shift)); - regs.gpr[RT(instr)] = result; - } -} - -void ld(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - s64 address = regs.gpr[RS(instr)] + (s16)instr; - if (check_address_error(0b111, address)) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); - return; - } - - u32 paddr = 0; - if(!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - s64 value = mem.Read64(regs, paddr); - regs.gpr[RT(instr)] = value; - } -} - -void lld(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) { - FireException(regs, ExceptionCode::ReservedInstruction, 0, true); - return; - } - - u64 address = regs.gpr[RS(instr)] + (s16)instr; - u32 paddr; - if (!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - if ((address & 0b111) > 0) { - FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); - } else { - regs.gpr[RT(instr)] = mem.Read64(regs, paddr); - regs.cop0.llbit = true; - regs.cop0.LLAddr = paddr >> 4; - } - } -} - -void ldl(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - u64 address = regs.gpr[RS(instr)] + (s16)instr; - u32 paddr = 0; - if (!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - s32 shift = 8 * ((address ^ 0) & 7); - u64 mask = 0xFFFFFFFFFFFFFFFF << shift; - u64 data = mem.Read64(regs, paddr & ~7); - s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data << shift)); - regs.gpr[RT(instr)] = result; - } -} - -void ldr(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - u64 address = regs.gpr[RS(instr)] + (s16)instr; - u32 paddr; - if (!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - s32 shift = 8 * ((address ^ 7) & 7); - u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; - u64 data = mem.Read64(regs, paddr & ~7); - s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data >> shift)); - regs.gpr[RT(instr)] = result; - } -} - -void lbu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - u64 address = regs.gpr[RS(instr)] + (s16)instr; - u32 paddr; - if (!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - u8 value = mem.Read8(regs, paddr); - regs.gpr[RT(instr)] = value; - } -} - -void lhu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - s64 address = regs.gpr[RS(instr)] + (s16)instr; - if ((address & 0b1) > 0) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); - return; - } - u32 paddr; - if (!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - u16 value = mem.Read16(regs, paddr); - regs.gpr[RT(instr)] = value; - } -} - -void lwu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - s64 address = regs.gpr[RS(instr)] + (s16)instr; - if ((address & 0b11) > 0) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorLoad, 0, true); - return; - } - - u32 paddr; - if (!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true); - } else { - u32 value = mem.Read32(regs, paddr); - regs.gpr[RT(instr)] = value; - } -} - -void sb(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - u64 address = regs.gpr[RS(instr)] + (s16)instr; - u32 paddr; - if (!MapVAddr(regs, STORE, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); - } else { - mem.Write8(regs, paddr, regs.gpr[RT(instr)]); - } -} - -void sc(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - u64 address = regs.gpr[RS(instr)] + (s16)instr; - - if ((address & 0b11) > 0) { - FireException(regs, ExceptionCode::AddressErrorStore, 0, true); - return; - } - - if(regs.cop0.llbit) { - regs.cop0.llbit = false; - u32 paddr = 0; - if(!MapVAddr(regs, STORE, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); - } else { - mem.Write32(regs, paddr, regs.gpr[RT(instr)]); - regs.gpr[RT(instr)] = 1; - } - } else { - regs.gpr[RT(instr)] = 0; - } -} - -void scd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) { - FireException(regs, ExceptionCode::ReservedInstruction, 0, true); - return; - } - - s64 address = regs.gpr[RS(instr)] + (s16)instr; - if ((address & 0b111) > 0) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorStore, 0, true); - return; - } - - if(regs.cop0.llbit) { - regs.cop0.llbit = false; - u32 paddr = 0; - if(!MapVAddr(regs, STORE, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); - } else { - mem.Write32(regs, paddr, regs.gpr[RT(instr)]); - regs.gpr[RT(instr)] = 1; - } - } else { - regs.gpr[RT(instr)] = 0; - } -} - -void sh(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - s64 address = regs.gpr[RS(instr)] + (s16)instr; - - u32 physical; - if(!MapVAddr(regs, STORE, address, physical)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); - } else { - mem.Write16(regs, physical, regs.gpr[RT(instr)]); - } -} - -void sw(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - s16 offset = instr; - u64 address = regs.gpr[RS(instr)] + offset; - if (check_address_error(0b11, address)) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorStore, 0, true); - return; - } - - u32 physical; - if(!MapVAddr(regs, STORE, address, physical)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); - } else { - mem.Write32(regs, physical, regs.gpr[RT(instr)]); - } -} - -void sd(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - s64 address = regs.gpr[RS(instr)] + (s16)instr; - if (check_address_error(0b111, address)) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorStore, 0, true); - return; - } - - u32 physical; - if(!MapVAddr(regs, STORE, address, physical)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); - } else { - mem.Write64(regs, physical, regs.gpr[RT(instr)]); - } -} - -void sdl(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - u64 address = regs.gpr[RS(instr)] + (s16)instr; - u32 paddr; - if (!MapVAddr(regs, STORE, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); - } else { - s32 shift = 8 * ((address ^ 0) & 7); - u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; - u64 data = mem.Read64(regs, paddr & ~7); - u64 rt = regs.gpr[RT(instr)]; - mem.Write64(regs, paddr & ~7, (data & ~mask) | (rt >> shift)); - } -} - -void sdr(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - u64 address = regs.gpr[RS(instr)] + (s16)instr; - u32 paddr; - if (!MapVAddr(regs, STORE, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); - } else { - s32 shift = 8 * ((address ^ 7) & 7); - u64 mask = 0xFFFFFFFFFFFFFFFF << shift; - u64 data = mem.Read64(regs, paddr & ~7); - u64 rt = regs.gpr[RT(instr)]; - mem.Write64(regs, paddr & ~7, (data & ~mask) | (rt << shift)); - } -} - -void swl(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - u64 address = regs.gpr[RS(instr)] + (s16)instr; - u32 paddr; - if (!MapVAddr(regs, STORE, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); - } else { - u32 shift = 8 * ((address ^ 0) & 3); - u32 mask = 0xFFFFFFFF >> shift; - u32 data = mem.Read32(regs, paddr & ~3); - u32 rt = regs.gpr[RT(instr)]; - mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt >> shift)); - } -} - -void swr(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - u64 address = regs.gpr[RS(instr)] + (s16)instr; - u32 paddr; - if (!MapVAddr(regs, STORE, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); - } else { - u32 shift = 8 * ((address ^ 3) & 3); - u32 mask = 0xFFFFFFFF << shift; - u32 data = mem.Read32(regs, paddr & ~3); - u32 rt = regs.gpr[RT(instr)]; - mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt << shift)); - } -} - -void ori(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s64 imm = (u16)instr; - s64 result = imm | regs.gpr[RS(instr)]; - regs.gpr[RT(instr)] = result; -} - -void or_(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - regs.gpr[RD(instr)] = regs.gpr[RS(instr)] | regs.gpr[RT(instr)]; - } -} - -void nor(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - regs.gpr[RD(instr)] = ~(regs.gpr[RS(instr)] | regs.gpr[RT(instr)]); - } -} - -void j(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - s32 target = (instr & 0x3ffffff) << 2; - s64 address = (regs.oldPC & ~0xfffffff) | target; - - branch(dyn, true, address); -} - -void jal(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.gpr[31] = regs.nextPC; - j(dyn, instr); -} - -void jalr(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - Mem& mem = dyn.mem; - branch(dyn, true, regs.gpr[RS(instr)]); - if(likely(RD(instr) != 0)) { - regs.gpr[RD(instr)] = regs.pc + 4; - } -} - -void slti(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s16 imm = instr; - regs.gpr[RT(instr)] = regs.gpr[RS(instr)] < imm; -} - -void sltiu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s16 imm = instr; - regs.gpr[RT(instr)] = (u64)regs.gpr[RS(instr)] < imm; -} - -void slt(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - regs.gpr[RD(instr)] = regs.gpr[RS(instr)] < regs.gpr[RT(instr)]; - } -} - -void sltu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - regs.gpr[RD(instr)] = (u64) regs.gpr[RS(instr)] < (u64) regs.gpr[RT(instr)]; - } -} - -void xori(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s64 imm = (u16)instr; - regs.gpr[RT(instr)] = regs.gpr[RS(instr)] ^ imm; -} - -void xor_(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - regs.gpr[RD(instr)] = regs.gpr[RT(instr)] ^ regs.gpr[RS(instr)]; - } -} - -void andi(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s64 imm = (u16)instr; - regs.gpr[RT(instr)] = regs.gpr[RS(instr)] & imm; -} - -void and_(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - regs.gpr[RD(instr)] = regs.gpr[RS(instr)] & regs.gpr[RT(instr)]; - } -} - -void sll(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - u8 sa = ((instr >> 6) & 0x1f); - s32 result = regs.gpr[RT(instr)] << sa; - regs.gpr[RD(instr)] = (s64) result; - } -} - -void sllv(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - u8 sa = (regs.gpr[RS(instr)]) & 0x1F; - u32 rt = regs.gpr[RT(instr)]; - s32 result = rt << sa; - regs.gpr[RD(instr)] = (s64) result; - } -} - -void dsll32(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - u8 sa = ((instr >> 6) & 0x1f); - s64 result = regs.gpr[RT(instr)] << (sa + 32); - regs.gpr[RD(instr)] = result; - } -} - -void dsll(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - u8 sa = ((instr >> 6) & 0x1f); - s64 result = regs.gpr[RT(instr)] << sa; - regs.gpr[RD(instr)] = result; - } -} - -void dsllv(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - s64 sa = regs.gpr[RS(instr)] & 63; - s64 result = regs.gpr[RT(instr)] << sa; - regs.gpr[RD(instr)] = result; - } -} - -void srl(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - u32 rt = regs.gpr[RT(instr)]; - u8 sa = ((instr >> 6) & 0x1f); - u32 result = rt >> sa; - regs.gpr[RD(instr)] = (s32) result; - } -} - -void srlv(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - u8 sa = (regs.gpr[RS(instr)] & 0x1F); - u32 rt = regs.gpr[RT(instr)]; - s32 result = rt >> sa; - regs.gpr[RD(instr)] = (s64) result; - } -} - -void dsrl(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - u64 rt = regs.gpr[RT(instr)]; - u8 sa = ((instr >> 6) & 0x1f); - u64 result = rt >> sa; - regs.gpr[RD(instr)] = s64(result); - } -} - -void dsrlv(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - u8 amount = (regs.gpr[RS(instr)] & 63); - u64 rt = regs.gpr[RT(instr)]; - u64 result = rt >> amount; - regs.gpr[RD(instr)] = s64(result); - } -} - -void dsrl32(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - u64 rt = regs.gpr[RT(instr)]; - u8 sa = ((instr >> 6) & 0x1f); - u64 result = rt >> (sa + 32); - regs.gpr[RD(instr)] = s64(result); - } -} - -void sra(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - s64 rt = regs.gpr[RT(instr)]; - u8 sa = ((instr >> 6) & 0x1f); - s32 result = rt >> sa; - regs.gpr[RD(instr)] = result; - } -} - -void srav(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s64 rt = regs.gpr[RT(instr)]; - if(likely(RD(instr) != 0)) { - s64 rs = regs.gpr[RS(instr)]; - u8 sa = rs & 0x1f; - s32 result = rt >> sa; - regs.gpr[RD(instr)] = result; - } -} - -void dsra(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - s64 rt = regs.gpr[RT(instr)]; - u8 sa = ((instr >> 6) & 0x1f); - s64 result = rt >> sa; - regs.gpr[RD(instr)] = result; - } -} - -void dsrav(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - s64 rt = regs.gpr[RT(instr)]; - s64 rs = regs.gpr[RS(instr)]; - s64 sa = rs & 63; - s64 result = rt >> sa; - regs.gpr[RD(instr)] = result; - } -} - -void dsra32(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - s64 rt = regs.gpr[RT(instr)]; - u8 sa = ((instr >> 6) & 0x1f); - s64 result = rt >> (sa + 32); - regs.gpr[RD(instr)] = result; - } -} - -void jr(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s64 address = regs.gpr[RS(instr)]; - branch(dyn, true, address); -} - -void dsub(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s64 rt = regs.gpr[RT(instr)]; - s64 rs = regs.gpr[RS(instr)]; - s64 result = rs - rt; - if(check_signed_underflow(rs, rt, result)) { - FireException(regs, ExceptionCode::Overflow, 0, true); - } else { - if(likely(RD(instr) != 0)) { - regs.gpr[RD(instr)] = result; - } - } -} - -void dsubu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - u64 rt = regs.gpr[RT(instr)]; - u64 rs = regs.gpr[RS(instr)]; - u64 result = rs - rt; - regs.gpr[RD(instr)] = s64(result); - } -} - -void sub(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s32 rt = regs.gpr[RT(instr)]; - s32 rs = regs.gpr[RS(instr)]; - s32 result = rs - rt; - if(check_signed_underflow(rs, rt, result)) { - FireException(regs, ExceptionCode::Overflow, 0, true); - } else { - if(likely(RD(instr) != 0)) { - regs.gpr[RD(instr)] = result; - } - } -} - -void subu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - u32 rt = regs.gpr[RT(instr)]; - u32 rs = regs.gpr[RS(instr)]; - u32 result = rs - rt; - regs.gpr[RD(instr)] = (s64) ((s32) result); - } -} - -void dmultu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - u64 rt = regs.gpr[RT(instr)]; - u64 rs = regs.gpr[RS(instr)]; - u128 result = (u128)rt * (u128)rs; - regs.lo = (s64)(result & 0xFFFFFFFFFFFFFFFF); - regs.hi = (s64)(result >> 64); -} - -void dmult(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s64 rt = regs.gpr[RT(instr)]; - s64 rs = regs.gpr[RS(instr)]; - s128 result = (s128)rt * (s128)rs; - regs.lo = result & 0xFFFFFFFFFFFFFFFF; - regs.hi = result >> 64; -} - -void multu(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - u32 rt = regs.gpr[RT(instr)]; - u32 rs = regs.gpr[RS(instr)]; - u64 result = (u64)rt * (u64)rs; - regs.lo = (s64)((s32)result); - regs.hi = (s64)((s32)(result >> 32)); -} - -void mult(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s32 rt = regs.gpr[RT(instr)]; - s32 rs = regs.gpr[RS(instr)]; - s64 result = (s64)rt * (s64)rs; - regs.lo = (s64)((s32)result); - regs.hi = (s64)((s32)(result >> 32)); -} - -void mflo(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - regs.gpr[RD(instr)] = regs.lo; - } -} - -void mfhi(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - if(likely(RD(instr) != 0)) { - regs.gpr[RD(instr)] = regs.hi; - } -} - -void mtlo(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.lo = regs.gpr[RS(instr)]; -} - -void mthi(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.hi = regs.gpr[RS(instr)]; -} - -void trap(JIT& dyn, bool cond) { - if(cond) { - FireException(dyn.regs, ExceptionCode::Trap, 0, true); - } -} - -void mtc2(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - dyn.cop2Latch = regs.gpr[RT(instr)]; -} - -void mfc2(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - s32 value = dyn.cop2Latch; - regs.gpr[RT(instr)] = value; -} - -void dmtc2(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - dyn.cop2Latch = regs.gpr[RT(instr)]; -} - -void dmfc2(JIT& dyn, u32 instr) { - Registers& regs = dyn.regs; - regs.gpr[RT(instr)] = dyn.cop2Latch; -} - -void ctc2(u32) { - -} - -void cfc2(u32) { - -} - -} \ No newline at end of file diff --git a/src/backend/core/jit/instructions.hpp b/src/backend/core/jit/instructions.hpp deleted file mode 100644 index 61fbf7fb..00000000 --- a/src/backend/core/jit/instructions.hpp +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once -#include - -namespace n64 { -void add(JIT&, u32); -void addu(JIT&, u32); -void addi(JIT&, u32); -void addiu(JIT&, u32); -void andi(JIT&, u32); -void and_(JIT&, u32); -void branch(JIT&, bool, s64); -void branch_likely(JIT&, bool, s64); -void b(JIT&, u32, bool); -void blink(JIT&, u32, bool); -void bl(JIT&, u32, bool); -void bllink(JIT&, u32, bool); -void dadd(JIT&, u32); -void daddu(JIT&, u32); -void daddi(JIT&, u32); -void daddiu(JIT&, u32); -void ddiv(JIT&, u32); -void ddivu(JIT&, u32); -void div(JIT&, u32); -void divu(JIT&, u32); -void dmult(JIT&, u32); -void dmultu(JIT&, u32); -void dsll(JIT&, u32); -void dsllv(JIT&, u32); -void dsll32(JIT&, u32); -void dsra(JIT&, u32); -void dsrav(JIT&, u32); -void dsra32(JIT&, u32); -void dsrl(JIT&, u32); -void dsrlv(JIT&, u32); -void dsrl32(JIT&, u32); -void dsub(JIT&, u32); -void dsubu(JIT&, u32); -void j(JIT&, u32); -void jr(JIT&, u32); -void jal(JIT&, u32); -void jalr(JIT&, u32); -void lui(JIT&, u32); -void lbu(JIT&, u32); -void lb(JIT&, u32); -void ld(JIT&, u32); -void ldl(JIT&, u32); -void ldr(JIT&, u32); -void lh(JIT&, u32); -void lhu(JIT&, u32); -void ll(JIT&, u32); -void lld(JIT&, u32); -void lw(JIT&, u32); -void lwl(JIT&, u32); -void lwu(JIT&, u32); -void lwr(JIT&, u32); -void mfhi(JIT&, u32); -void mflo(JIT&, u32); -void mult(JIT&, u32); -void multu(JIT&, u32); -void mthi(JIT&, u32); -void mtlo(JIT&, u32); -void nor(JIT&, u32); -void sb(JIT&, u32); -void sc(JIT&, u32); -void scd(JIT&, u32); -void sd(JIT&, u32); -void sdl(JIT&, u32); -void sdr(JIT&, u32); -void sh(JIT&, u32); -void sw(JIT&, u32); -void swl(JIT&, u32); -void swr(JIT&, u32); -void slti(JIT&, u32); -void sltiu(JIT&, u32); -void slt(JIT&, u32); -void sltu(JIT&, u32); -void sll(JIT&, u32); -void sllv(JIT&, u32); -void sub(JIT&, u32); -void subu(JIT&, u32); -void sra(JIT&, u32); -void srav(JIT&, u32); -void srl(JIT&, u32); -void srlv(JIT&, u32); -void trap(JIT&, bool); -void or_(JIT&, u32); -void ori(JIT&, u32); -void xor_(JIT&, u32); -void xori(JIT&, u32); -void mtc2(JIT&, u32); -void mfc2(JIT&, u32); -void dmtc2(JIT&, u32); -void dmfc2(JIT&, u32); -} \ No newline at end of file diff --git a/src/backend/core/mmio/PIF.cpp b/src/backend/core/mmio/PIF.cpp index b3b90058..fa21f3df 100644 --- a/src/backend/core/mmio/PIF.cpp +++ b/src/backend/core/mmio/PIF.cpp @@ -349,6 +349,7 @@ void PIF::UpdateController() { } else { yclamped /= SDL_JOYSTICK_AXIS_MAX; } + yclamped *= 86; joybusDevices[channel].controller.joy_x = xclamped; diff --git a/src/backend/core/mmio/PIF/Device.cpp b/src/backend/core/mmio/PIF/Device.cpp index 231582fd..c3036827 100644 --- a/src/backend/core/mmio/PIF/Device.cpp +++ b/src/backend/core/mmio/PIF/Device.cpp @@ -4,12 +4,12 @@ namespace n64 { void PIF::InitDevices(SaveType saveType) { - for (int i = 0; i < 4; i++) { //TODO: make this configurable + joybusDevices[0].type = JOYBUS_CONTROLLER; + joybusDevices[0].accessoryType = ACCESSORY_MEMPACK; + for (int i = 1; i < 4; i++) { //TODO: make this configurable joybusDevices[i].type = JOYBUS_NONE; joybusDevices[i].accessoryType = ACCESSORY_NONE; } - joybusDevices[0].type = JOYBUS_CONTROLLER; - joybusDevices[0].accessoryType = ACCESSORY_MEMPACK; if (saveType == SAVE_EEPROM_4k) { joybusDevices[4].type = JOYBUS_4KB_EEPROM; diff --git a/src/backend/core/mmio/VI.cpp b/src/backend/core/mmio/VI.cpp index c2b507d7..1a4e68ac 100644 --- a/src/backend/core/mmio/VI.cpp +++ b/src/backend/core/mmio/VI.cpp @@ -69,7 +69,7 @@ void VI::Write(MI& mi, Registers& regs, u32 paddr, u32 val) { case 0x04400018: { vsync = val & 0x3FF; numHalflines = vsync >> 1; - cyclesPerHalfline = N64_CYCLES_PER_FRAME(false) / numHalflines; + cyclesPerHalfline = N64_CYCLES_PER_FRAME(isPal) / numHalflines; } break; case 0x0440001C: { hsync = val & 0x3FF; diff --git a/src/backend/core/mmio/VI.hpp b/src/backend/core/mmio/VI.hpp index 1c2c1f6f..95992c90 100644 --- a/src/backend/core/mmio/VI.hpp +++ b/src/backend/core/mmio/VI.hpp @@ -88,6 +88,7 @@ struct VI { u32 origin, width, current; u32 vsync, hsync, intr; AxisStart hstart{}, vstart{}; + bool isPal = false; int swaps{}; int numHalflines; int numFields; diff --git a/src/common.hpp b/src/common.hpp index 1b90f57d..4fcb5ff3 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -37,4 +37,4 @@ using m128i = __m128i; #define unlikely(exp) __builtin_expect(exp, 0) #define likely(exp) __builtin_expect(exp, 1) -#define INLINE static inline __attribute__((always_inline)) \ No newline at end of file +#define FORCE_INLINE inline __attribute__((always_inline)) \ No newline at end of file diff --git a/src/frontend/App.cpp b/src/frontend/App.cpp index d3a1b304..c5eb2006 100644 --- a/src/frontend/App.cpp +++ b/src/frontend/App.cpp @@ -9,10 +9,17 @@ App::App() : window(core) { void App::Run() { SDL_EventState(SDL_DROPFILE, SDL_ENABLE); - n64::SI& si = core.cpu->mem.mmio.si; + n64::SI& si = core.cpu.mem.mmio.si; while (!core.done) { - core.Run(window, window.settings.GetVolumeL(), window.settings.GetVolumeL()); + if(core.romLoaded) { + if(!core.pause) { + core.Run(window.settings.GetVolumeL(), window.settings.GetVolumeR()); + } + UpdateScreenParallelRdp(core, window, core.GetVI()); + } else { + UpdateScreenParallelRdpNoGame(core, window); + } SDL_Event event; while (SDL_PollEvent(&event)) { diff --git a/src/frontend/imgui/Settings.cpp b/src/frontend/imgui/Settings.cpp index 50b2f964..c4facbca 100644 --- a/src/frontend/imgui/Settings.cpp +++ b/src/frontend/imgui/Settings.cpp @@ -27,34 +27,16 @@ Settings::Settings(n64::Core& core) { if(fileExists) { settingsFile = std::fstream("resources/settings.json", std::fstream::in | std::fstream::out); settings = json::parse(settingsFile); - auto entryCpuType = settings["cpu"]["type"]; - if(!entryCpuType.empty()) { - cpuType = entryCpuType.get(); - if(cpuType == "jit") { - core.cpuType = n64::CpuType::JIT; - } else if(cpuType == "interpreter") { - core.cpuType = n64::CpuType::Interpreter; - } else { - Util::panic("Unrecognized cpu type: {}\n", cpuType); - } - } else { - settingsFile.clear(); - settings["cpu"]["type"] = "interpreter"; - settingsFile << settings; - core.cpuType = n64::CpuType::Interpreter; - } checkjsonentry(volumeR, float, "audio", "volumeR", 0.5); checkjsonentry(volumeL, float, "audio", "volumeL", 0.5); checkjsonentry(lockChannels, bool, "audio", "lockChannels", true); } else { settingsFile = std::fstream("resources/settings.json", std::fstream::trunc | std::fstream::in | std::fstream::out); - settings["cpu"]["type"] = "interpreter"; settings["audio"]["volumeR"] = 0.5; settings["audio"]["volumeL"] = 0.5; settings["audio"]["lockChannels"] = true; - core.cpuType = n64::CpuType::Interpreter; volumeR = 0.5; volumeL = 0.5; lockChannels = true; @@ -62,17 +44,6 @@ Settings::Settings(n64::Core& core) { settingsFile << settings; } settingsFile.close(); - - switch(core.cpuType) { - case n64::CpuType::Interpreter: - core.cpu = std::make_unique(); - break; - case n64::CpuType::JIT: - core.cpu = std::make_unique(); - break; - case n64::CpuType::COUNT: - Util::panic("BRUH\n"); - } } Settings::~Settings() { @@ -81,7 +52,6 @@ Settings::~Settings() { if(fileExists) { settingsFile = std::fstream("resources/settings.json", std::fstream::trunc | std::fstream::out); - settings["cpu"]["type"] = cpuType; settings["audio"]["volumeR"] = volumeR; settings["audio"]["volumeL"] = volumeL; settings["audio"]["lockChannels"] = lockChannels; @@ -89,7 +59,6 @@ Settings::~Settings() { } else { settingsFile = std::fstream("resources/settings.json", std::fstream::out); - settings["cpu"]["type"] = cpuType; settings["audio"]["volumeR"] = volumeR; settings["audio"]["volumeL"] = volumeL; settings["audio"]["lockChannels"] = lockChannels; @@ -103,30 +72,12 @@ void Settings::RenderWidget(bool& show) { if(show) { ImGui::OpenPopup("Settings"); if(ImGui::BeginPopupModal("Settings", &show)) { - enum class SelectedSetting { CPU, Audio, COUNT }; + enum class SelectedSetting { Audio, COUNT }; static SelectedSetting selectedSetting = SelectedSetting::Audio; - const char *categories[(int)SelectedSetting::COUNT] = { "CPU", "Audio" }; + const char *categories[(int)SelectedSetting::COUNT] = { "Audio" }; CreateComboList("##", (int*)&selectedSetting, categories, (int)SelectedSetting::COUNT); ImGui::Separator(); switch (selectedSetting) { - case SelectedSetting::CPU: { - const char* cpuTypes[(int)n64::CpuType::COUNT] = { "Interpreter", "JIT" }; - static n64::CpuType currentType = n64::CpuType::Interpreter; - if (cpuType == "jit") currentType = n64::CpuType::JIT; - - if (CreateComboList("Core type", (int*)¤tType, cpuTypes, (int)n64::CpuType::COUNT)) { - switch (currentType) { - case n64::CpuType::Interpreter: - cpuType = "interpreter"; - break; - case n64::CpuType::JIT: - cpuType = "jit"; - break; - case n64::CpuType::COUNT: - Util::panic("BRUH\n"); - } - } - } break; case SelectedSetting::Audio: ImGui::Checkbox("Lock channels", &lockChannels); ImGui::SliderFloat("Volume L", &volumeL, 0, 1, "%.2f", ImGuiSliderFlags_NoInput); diff --git a/src/frontend/imgui/Settings.hpp b/src/frontend/imgui/Settings.hpp index 407db897..e52f5e10 100644 --- a/src/frontend/imgui/Settings.hpp +++ b/src/frontend/imgui/Settings.hpp @@ -11,11 +11,9 @@ struct Settings { inline float GetVolumeL() const { return volumeL; }; inline float GetVolumeR() const { return volumeR; }; inline bool GetLockChannels() const { return lockChannels; } - inline std::string GetCpuType() const { return cpuType; } void RenderWidget(bool& show); private: - std::string cpuType = "interpreter"; float volumeL = 0.0, volumeR = 0.0; bool lockChannels = true; json settings; diff --git a/src/frontend/imgui/Window.cpp b/src/frontend/imgui/Window.cpp index d430b015..0b03a4a0 100644 --- a/src/frontend/imgui/Window.cpp +++ b/src/frontend/imgui/Window.cpp @@ -11,7 +11,7 @@ namespace fs = std::filesystem; Window::Window(n64::Core& core) : settings(core) { InitSDL(); - InitParallelRDP(core.cpu->mem.GetRDRAM(), window); + InitParallelRDP(core.cpu.mem.GetRDRAM(), window); InitImgui(); NFD::Init(); } @@ -152,7 +152,7 @@ ImDrawData* Window::Present(n64::Core& core) { void Window::LoadROM(n64::Core& core, const std::string &path) { if(!path.empty()) { core.LoadROM(path); - gameName = core.cpu->mem.rom.gameNameDB; + gameName = core.cpu.mem.rom.gameNameDB; if(gameName.empty()) { gameName = fs::path(path).stem().string(); @@ -181,13 +181,13 @@ void Window::RenderMainMenuBar(n64::Core &core) { } } if (ImGui::MenuItem("Dump RDRAM")) { - core.cpu->mem.DumpRDRAM(); + core.cpu.mem.DumpRDRAM(); } if (ImGui::MenuItem("Dump IMEM")) { - core.cpu->mem.DumpIMEM(); + core.cpu.mem.DumpIMEM(); } if (ImGui::MenuItem("Dump DMEM")) { - core.cpu->mem.DumpDMEM(); + core.cpu.mem.DumpDMEM(); } if (ImGui::MenuItem("Exit")) { core.done = true; @@ -232,8 +232,8 @@ void Window::Render(n64::Core& core) { static u32 lastFrame = 0; if(!core.pause && lastFrame < ticks - 1000) { lastFrame = ticks; - windowTitle += fmt::format(" | {:02d} VI/s", core.cpu->mem.mmio.vi.swaps); - core.cpu->mem.mmio.vi.swaps = 0; + windowTitle += fmt::format(" | {:02d} VI/s", core.cpu.mem.mmio.vi.swaps); + core.cpu.mem.mmio.vi.swaps = 0; SDL_SetWindowTitle(window, windowTitle.c_str()); windowTitle = shadowWindowTitle; }