From 1c6f89f85617695d02ad608deaae4d17c11bbef8 Mon Sep 17 00:00:00 2001 From: SimoneN64 Date: Thu, 18 Jan 2024 22:09:27 +0100 Subject: [PATCH] Yeah --- external/parallel-rdp/ParallelRDPWrapper.cpp | 5 +- external/parallel-rdp/ParallelRDPWrapper.hpp | 4 +- src/backend/Core.hpp | 1 - src/backend/core/JIT.cpp | 95 -- src/backend/core/JIT.hpp | 246 ---- src/backend/core/JIT/CMakeLists.txt | 4 - src/backend/core/JIT/decode.cpp | 172 --- src/backend/core/JIT/instructions.cpp | 1037 ----------------- src/backend/core/mem/Flash.cpp | 2 +- src/backend/core/mmio/PIF.hpp | 1 + src/backend/core/registers/Cop1.cpp | 157 --- .../core/registers/cop/cop1instructions.cpp | 1 - src/frontend/RenderWidget.cpp | 13 +- src/frontend/RenderWidget.hpp | 38 +- 14 files changed, 44 insertions(+), 1732 deletions(-) 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/decode.cpp delete mode 100644 src/backend/core/JIT/instructions.cpp diff --git a/external/parallel-rdp/ParallelRDPWrapper.cpp b/external/parallel-rdp/ParallelRDPWrapper.cpp index 402c5133..aa8e75e0 100644 --- a/external/parallel-rdp/ParallelRDPWrapper.cpp +++ b/external/parallel-rdp/ParallelRDPWrapper.cpp @@ -11,7 +11,6 @@ using namespace Vulkan; using namespace RDP; static CommandProcessor* command_processor; -static WSI* wsi; static std::unique_ptr windowInfo; VkQueue GetGraphicsQueue() { @@ -125,13 +124,13 @@ private: Program* fullscreen_quad_program; -WSI* LoadWSIPlatform(Vulkan::WSIPlatform* wsi_platform, std::unique_ptr&& newWindowInfo) { +WSI* LoadWSIPlatform(Vulkan::InstanceFactory* instanceFactory, Vulkan::WSIPlatform* wsi_platform, std::unique_ptr&& newWindowInfo) { wsi = new WSI(); wsi->set_backbuffer_srgb(false); wsi->set_platform(wsi_platform); wsi->set_present_mode(PresentMode::SyncToVBlank); Context::SystemHandles handles; - if (!wsi->init_simple(1, handles)) { + if (!wsi->init_simple(instanceFactory, 1, handles)) { Util::panic("Failed to initialize WSI!"); } diff --git a/external/parallel-rdp/ParallelRDPWrapper.hpp b/external/parallel-rdp/ParallelRDPWrapper.hpp index 8056e1f3..b0d98842 100644 --- a/external/parallel-rdp/ParallelRDPWrapper.hpp +++ b/external/parallel-rdp/ParallelRDPWrapper.hpp @@ -23,6 +23,8 @@ public: } }; +static Vulkan::WSI* wsi; + VkRenderPass GetVkRenderPass(); VkQueue GetGraphicsQueue(); VkInstance GetVkInstance(); @@ -33,7 +35,7 @@ VkFormat GetVkFormat(); VkCommandBuffer GetVkCommandBuffer(); void SubmitRequestedVkCommandBuffer(); void LoadParallelRDP(const u8* rdram); -Vulkan::WSI* LoadWSIPlatform(Vulkan::WSIPlatform* wsi_platform, std::unique_ptr&& newWindowInfo); +Vulkan::WSI* LoadWSIPlatform(Vulkan::InstanceFactory*, Vulkan::WSIPlatform* wsi_platform, std::unique_ptr&& newWindowInfo); void UpdateScreenParallelRdp(n64::Core& core, n64::VI& vi); void ParallelRdpEnqueueCommand(int command_length, u32* buffer); void ParallelRdpOnFullSync(); diff --git a/src/backend/Core.hpp b/src/backend/Core.hpp index b79a1139..f51822e3 100644 --- a/src/backend/Core.hpp +++ b/src/backend/Core.hpp @@ -1,7 +1,6 @@ #pragma once #include #include -#include #include #include diff --git a/src/backend/core/JIT.cpp b/src/backend/core/JIT.cpp deleted file mode 100644 index ff2ac465..00000000 --- a/src/backend/core/JIT.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include - -namespace n64 { -using namespace Xbyak; -JIT::JIT() : CodeGenerator(32*1024*1024, AutoGrow) { } - -void JIT::Reset() { - reset(); - regs.Reset(); - mem.Reset(); -} - -bool JIT::ShouldServiceInterrupt() { - 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; -} - -void JIT::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); - } -} - -Fn JIT::Recompile() { - bool stable = true; - cycles = 0; - prologue(); - mov(rbp, u64(this)); - mov(rdi, u64(this) + THIS_OFFSET(regs)); - while(stable) { - cycles++; - CheckCompareInterrupt(); - - mov(rax, REG(byte, delaySlot)); - mov(REG(byte, prevDelaySlot), rax); - mov(REG(byte, delaySlot), 0); - - u32 paddr = 0; - if (!MapVAddr(regs, LOAD, regs.pc, paddr)) { - mov(rsi, regs.pc); - emitCall(HandleTLBException); - mov(rsi, u64(GetTLBExceptionCode(regs.cop0.tlbError, LOAD))); - CodeGenerator::xor_(rdx, rdx); - CodeGenerator::xor_(rcx, rcx); - emitCall(FireException); - goto _epilogue; - } - - u32 instr = mem.Read(regs, paddr); - stable = isStable(instr); - Emit(instr); - - if (ShouldServiceInterrupt()) { - mov(rsi, u64(ExceptionCode::Interrupt)); - CodeGenerator::xor_(rdx, rdx); - CodeGenerator::xor_(rcx, rcx); - push(rax); - call(FireException); - goto _epilogue; - } - - mov(rax, REG(qword, pc)); - mov(REG(qword, oldPC), rax); - mov(rax, REG(qword, nextPC)); - mov(REG(qword, pc), rax); - CodeGenerator::add(REG(qword, nextPC), 4); - } -_epilogue: - epilogue(); - ready(); - return getCode(); -} - -int JIT::Step() { - if(!blocks[BLOCKCACHE_OUTER_INDEX(regs.pc)]) { - blocks[BLOCKCACHE_OUTER_INDEX(regs.pc)] = (Fn*)calloc(BLOCKCACHE_INNER_SIZE, 1); - blocks[BLOCKCACHE_OUTER_INDEX(regs.pc)][BLOCKCACHE_INNER_INDEX(regs.pc)] = Recompile(); - } - - if (!blocks[BLOCKCACHE_OUTER_INDEX(regs.pc)][BLOCKCACHE_INNER_INDEX(regs.pc)]) { - blocks[BLOCKCACHE_OUTER_INDEX(regs.pc)][BLOCKCACHE_INNER_INDEX(regs.pc)] = Recompile(); - } - - return blocks[BLOCKCACHE_OUTER_INDEX(regs.pc)][BLOCKCACHE_INNER_INDEX(regs.pc)](); -} -} diff --git a/src/backend/core/JIT.hpp b/src/backend/core/JIT.hpp deleted file mode 100644 index f78f600f..00000000 --- a/src/backend/core/JIT.hpp +++ /dev/null @@ -1,246 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include "CpuDefinitions.hpp" - -namespace n64 { -using Fn = int(*)(); -#define THIS_OFFSET(x) ((uintptr_t)(&x) - (uintptr_t)this) -#define GPR_OFFSET(x) ((uintptr_t)®s.gpr[(x)] - (uintptr_t)this) -#define REG_OFFSET(member) ((uintptr_t)®s.member - (uintptr_t)this) -#define GPR(ptr, x) ptr[rdi + GPR_OFFSET(x)] -#define REG(ptr, member) ptr[rdi + REG_OFFSET(member)] -// 4KiB aligned pages -#define BLOCKCACHE_OUTER_SHIFT 12 -#define BLOCKCACHE_PAGE_SIZE (1 << BLOCKCACHE_OUTER_SHIFT) -#define BLOCKCACHE_OUTER_SIZE (0x80000000 >> BLOCKCACHE_OUTER_SHIFT) -// word aligned instructions -#define BLOCKCACHE_INNER_SIZE (BLOCKCACHE_PAGE_SIZE >> 2) -#define BLOCKCACHE_INNER_INDEX(physical) (((physical) & (BLOCKCACHE_PAGE_SIZE - 1)) >> 2) -#define BLOCKCACHE_OUTER_INDEX(physical) ((physical) >> BLOCKCACHE_OUTER_SHIFT) - -struct JIT : BaseCPU, Xbyak::CodeGenerator { - JIT(); - ~JIT() override = default; - int Step() override; - void Reset() override; - friend struct Cop1; - friend struct Cop0; -private: - int cycles = 0; - bool ShouldServiceInterrupt() override; - void CheckCompareInterrupt() override; - Fn Recompile(); - - template - void emitMemberCall(T func, void* thisObj) { - T* funcPtr; - auto thisPtr = reinterpret_cast(thisObj); -#ifdef ABI_WINDOWS - static_assert(sizeof(T) == 8, "[JIT]: Invalid size for member function pointer"); - std::memcpy(&funcPtr, &func, sizeof(T)); -#elif defined(ABI_UNIX) - static_assert(sizeof(T) == 16, "[JIT]: Invalid size for member function pointer"); - uintptr_t tmpArr[2]; - std::memcpy(tmpArr, &func, sizeof(T)); - funcPtr = reinterpret_cast(tmpArr[0]); - thisPtr += tmpArr[1]; -#else - Util::panic("Huh?!"); -#endif - - push(rdi); - if(thisPtr == reinterpret_cast(this)) { - mov(rdi, rbp); - } else { - mov(rdi, (uintptr_t)thisPtr); - } - call(funcPtr); - pop(rdi); - } - - template - void emitCall(T func) { - T* funcPtr; -#ifdef ABI_WINDOWS - std::memcpy(&funcPtr, &func, sizeof(T)); -#elif defined(ABI_UNIX) - uintptr_t tmpArr[2]; - std::memcpy(tmpArr, &func, sizeof(T)); - funcPtr = reinterpret_cast(tmpArr[0]); -#else - Util::panic("Huh?!"); -#endif - - push(rdi); - call(funcPtr); - pop(rdi); - } - - bool isStable(u32 instr) { - u8 mask = (instr >> 26) & 0x3f; - switch(mask) { - case SPECIAL: - mask = instr & 0x3f; - switch(mask) { - case JR ... JALR: - case SYSCALL: case BREAK: - case TGE ... TNE: - return false; - default: return true; - } - case REGIMM: - case J ... BGTZ: - case BEQL ... BGTZL: - return false; - case COP1: - mask = (instr >> 16) & 0x1f; - if(mask >= 0 && mask <= 3) { - return false; - } - default: return true; - } - } - - FORCE_INLINE void prologue() { - const Xbyak::Reg64 allRegs[]{rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15}; - for(auto r : allRegs) { - push(r); - } - } - - FORCE_INLINE void epilogue() { - const Xbyak::Reg64 allRegs[]{r15, r14, r13, r12, r11, r10, r9, r8, rdi, rsi, rbp, rsp, rbx, rdx, rcx, rax}; - for(auto r : allRegs) { - pop(r); - } - mov(rax, cycles); - ret(); - } - - Fn* blocks[BLOCKCACHE_OUTER_SIZE]{}; - - std::vector Serialize() override { return {}; } - void Deserialize(const std::vector&) override { } - - void cop2Decode(u32); - void special(u32); - void regimm(u32); - void Emit(u32); - void add(u32); - void addu(u32); - void addi(u32); - void addiu(u32); - void andi(u32); - void and_(u32); - void bltz(u32); - void bgez(u32); - void bltzl(u32); - void bgezl(u32); - void bltzal(u32); - void bgezal(u32); - void bltzall(u32); - void bgezall(u32); - void beq(u32); - void bne(u32); - void blez(u32); - void bgtz(u32); - void beql(u32); - void bnel(u32); - void blezl(u32); - void bgtzl(u32); - void dadd(u32); - void daddu(u32); - void daddi(u32); - void daddiu(u32); - void ddiv(u32); - void ddivu(u32); - void div(u32); - void divu(u32); - void dmult(u32); - void dmultu(u32); - void dsll(u32); - void dsllv(u32); - void dsll32(u32); - void dsra(u32); - void dsrav(u32); - void dsra32(u32); - void dsrl(u32); - void dsrlv(u32); - void dsrl32(u32); - void dsub(u32); - void dsubu(u32); - void j(u32); - void jr(u32); - void jal(u32); - void jalr(u32); - void lui(u32); - void lbu(u32); - void lb(u32); - void ld(u32); - void ldl(u32); - void ldr(u32); - void lh(u32); - void lhu(u32); - void ll(u32); - void lld(u32); - void lw(u32); - void lwl(u32); - void lwu(u32); - void lwr(u32); - void mfhi(u32); - void mflo(u32); - void mult(u32); - void multu(u32); - void mthi(u32); - void mtlo(u32); - void nor(u32); - void sb(u32); - void sc(u32); - void scd(u32); - void sd(u32); - void sdl(u32); - void sdr(u32); - void sh(u32); - void sw(u32); - void swl(u32); - void swr(u32); - void slti(u32); - void sltiu(u32); - void slt(u32); - void sltu(u32); - void sll(u32); - void sllv(u32); - void sub(u32); - void subu(u32); - void sra(u32); - void srav(u32); - void srl(u32); - void srlv(u32); - void tgei(u32); - void tgeiu(u32); - void tlti(u32); - void tltiu(u32); - void teqi(u32); - void tnei(u32); - void tge(u32); - void tgeu(u32); - void tlt(u32); - void tltu(u32); - void teq(u32); - void tne(u32); - void or_(u32); - void ori(u32); - void xor_(u32); - void xori(u32); - - void mtc2(u32); - void mfc2(u32); - void dmtc2(u32); - void dmfc2(u32); - void ctc2(u32); - void cfc2(u32); -}; -} diff --git a/src/backend/core/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/decode.cpp b/src/backend/core/JIT/decode.cpp deleted file mode 100644 index b9008fa4..00000000 --- a/src/backend/core/JIT/decode.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include -#include - -namespace n64 { -void JIT::special(u32 instr) { - u8 mask = (instr & 0x3F); - // 00rr_rccc - switch (mask) { // TODO: named constants for clearer code - case SLL: - if (instr != 0) { - sll(instr); - } - break; - case SRL: srl(instr); break; - case SRA: sra(instr); break; - case SLLV: sllv(instr); break; - case SRLV: srlv(instr); break; - case SRAV: srav(instr); break; - case JR: jr(instr); break; - case JALR: jalr(instr); break; - case SYSCALL: FireException(regs, ExceptionCode::Syscall, 0, regs.oldPC); break; - case BREAK: FireException(regs, ExceptionCode::Breakpoint, 0, regs.oldPC); break; - case SYNC: break; // SYNC - case MFHI: mfhi(instr); break; - case MTHI: mthi(instr); break; - case MFLO: mflo(instr); break; - case MTLO: mtlo(instr); break; - case DSLLV: dsllv(instr); break; - case DSRLV: dsrlv(instr); break; - case DSRAV: dsrav(instr); break; - case MULT: mult(instr); break; - case MULTU: multu(instr); break; - case DIV: div(instr); break; - case DIVU: divu(instr); break; - case DMULT: dmult(instr); break; - case DMULTU: dmultu(instr); break; - case DDIV: ddiv(instr); break; - case DDIVU: ddivu(instr); break; - case ADD: add(instr); break; - case ADDU: addu(instr); break; - case SUB: sub(instr); break; - case SUBU: subu(instr); break; - case AND: and_(instr); break; - case OR: or_(instr); break; - case XOR: xor_(instr); break; - case NOR: nor(instr); break; - case SLT: slt(instr); break; - case SLTU: sltu(instr); break; - case DADD: dadd(instr); break; - case DADDU: daddu(instr); break; - case DSUB: dsub(instr); break; - case DSUBU: dsubu(instr); break; - case TGE: tge(instr); break; - case TGEU: tgeu(instr); break; - case TLT: tlt(instr); break; - case TLTU: tltu(instr); break; - case TEQ: teq(instr); break; - case TNE: tne(instr); break; - case DSLL: dsll(instr); break; - case DSRL: dsrl(instr); break; - case DSRA: dsra(instr); break; - case DSLL32: dsll32(instr); break; - case DSRL32: dsrl32(instr); break; - case DSRA32: dsra32(instr); break; - default: - Util::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 7, mask & 7, instr, (u64)regs.oldPC); - } -} - -void JIT::regimm(u32 instr) { - u8 mask = ((instr >> 16) & 0x1F); - // 000r_rccc - switch (mask) { // TODO: named constants for clearer code - case BLTZ: bltz(instr); break; - case BGEZ: bgez(instr); break; - case BLTZL: bltzl(instr); break; - case BGEZL: bgezl(instr); break; - case TGEI: tgei(instr); break; - case TGEIU: tgeiu(instr); break; - case TLTI: tlti(instr); break; - case TLTIU: tltiu(instr); break; - case TEQI: teqi(instr); break; - case TNEI: tnei(instr); break; - case BLTZAL: bltzal(instr); break; - case BGEZAL: bgezal(instr); break; - case BLTZALL: bltzall(instr); break; - case BGEZALL: bgezall(instr); break; - default: - Util::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", (mask >> 3) & 3, mask & 7, instr, (u64)regs.oldPC); - } -} - -void JIT::cop2Decode(u32 instr) { - if(!regs.cop0.status.cu2) { - FireException(regs, ExceptionCode::CoprocessorUnusable, 2, regs.oldPC); - return; - } - switch(RS(instr)) { - case 0x00: mfc2(instr); break; - case 0x01: dmfc2(instr); break; - case 0x02: cfc2(instr); break; - case 0x04: mtc2(instr); break; - case 0x05: dmtc2(instr); break; - case 0x06: ctc2(instr); break; - default: - FireException(regs, ExceptionCode::ReservedInstruction, 2, regs.oldPC); - } -} - -void JIT::Emit(u32 instr) { - u8 mask = (instr >> 26) & 0x3f; - // 00rr_rccc - switch(mask) { // TODO: named constants for clearer code - case SPECIAL: special(instr); break; - case REGIMM: regimm(instr); break; - case J: j(instr); break; - case JAL: jal(instr); break; - case BEQ: beq(instr); break; - case BNE: bne(instr); break; - case BLEZ: blez(instr); break; - case BGTZ: bgtz(instr); break; - case ADDI: addi(instr); break; - case ADDIU: addiu(instr); break; - case SLTI: slti(instr); break; - case SLTIU: sltiu(instr); break; - case ANDI: andi(instr); break; - case ORI: ori(instr); break; - case XORI: xori(instr); break; - case LUI: lui(instr); break; - case COP0: regs.cop0.decode(*this, instr); break; - case COP1: regs.cop1.decode(*this, instr); break; - case COP2: cop2Decode(instr); break; - case BEQL: beql(instr); break; - case BNEL: bnel(instr); break; - case BLEZL: blezl(instr); break; - case BGTZL: bgtzl(instr); break; - case DADDI: daddi(instr); break; - case DADDIU: daddiu(instr); break; - case LDL: ldl(instr); break; - case LDR: ldr(instr); break; - case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC); break; - case LB: lb(instr); break; - case LH: lh(instr); break; - case LWL: lwl(instr); break; - case LW: lw(instr); break; - case LBU: lbu(instr); break; - case LHU: lhu(instr); break; - case LWR: lwr(instr); break; - case LWU: lwu(instr); break; - case SB: sb(instr); break; - case SH: sh(instr); break; - case SWL: swl(instr); break; - case SW: sw(instr); break; - case SDL: sdl(instr); break; - case SDR: sdr(instr); break; - case SWR: swr(instr); break; - case CACHE: break; // CACHE - case LL: ll(instr); break; - case LWC1: regs.cop1.lwc1(*this, mem, instr); break; - case LLD: lld(instr); break; - case LDC1: regs.cop1.ldc1(*this, mem, instr); break; - case LD: ld(instr); break; - case SC: sc(instr); break; - case SWC1: regs.cop1.swc1(*this, mem, instr); break; - case SCD: scd(instr); break; - case SDC1: regs.cop1.sdc1(*this, mem, instr); break; - case SD: sd(instr); break; - default: - Util::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", mask, instr, (u64)regs.oldPC); - } -} -} diff --git a/src/backend/core/JIT/instructions.cpp b/src/backend/core/JIT/instructions.cpp deleted file mode 100644 index 7ec1f46c..00000000 --- a/src/backend/core/JIT/instructions.cpp +++ /dev/null @@ -1,1037 +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 JIT::add(u32 instr) { - if (RD(instr) != 0) [[likely]] { - movsx(eax, GPR(dword, RS(instr))); // rs - movsx(ecx, GPR(dword, RT(instr))); // rt - CodeGenerator::add(eax, ecx); - mov(GPR(dword, RD(instr)), eax); // rd - } -} - -void JIT::addu(u32 instr) { - add(instr); -} - -void JIT::addi(u32 instr) { - if (RT(instr) != 0) [[likely]] { - movsx(eax, GPR(dword, RS(instr))); - mov(ecx, s32(s16(instr))); - CodeGenerator::add(eax, ecx); - mov(GPR(dword, RT(instr)), eax); - } -} - -void JIT::addiu(u32 instr) { - addi(instr); -} - -void JIT::dadd(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rax, GPR(qword, RS(instr))); // rs - mov(rcx, GPR(qword, RT(instr))); // rt - CodeGenerator::add(rax, rcx); - mov(GPR(qword, RD(instr)), rax); // rd - } -} - -void JIT::bltz(u32) { - -} - -void JIT::bgez(u32) { - -} - -void JIT::bltzl(u32) { - -} - -void JIT::bgezl(u32) { - -} - -void JIT::bltzal(u32) { - -} - -void JIT::bgezal(u32) { - -} - -void JIT::bltzall(u32) { - -} - -void JIT::bgezall(u32) { - -} - -void JIT::beq(u32) { - -} - -void JIT::bne(u32) { - -} - -void JIT::blez(u32) { - -} - -void JIT::bgtz(u32) { - -} - -void JIT::beql(u32) { - -} - -void JIT::bnel(u32) { - -} - -void JIT::blezl(u32) { - -} - -void JIT::bgtzl(u32) { - -} - -void JIT::daddu(u32 instr) { - dadd(instr); -} - -void JIT::daddi(u32 instr) { - if (RT(instr) != 0) [[likely]] { - mov(rax, GPR(qword, RS(instr))); - mov(rcx, s64(s16(instr))); - CodeGenerator::add(rax, rcx); - mov(GPR(qword, RT(instr)), rax); - } -} - -void JIT::daddiu(u32 instr) { - daddi(instr); -} - -void JIT::div(u32 instr) { - movsxd(rax, GPR(dword, RS(instr))); // dividend - movsxd(rcx, GPR(dword, RT(instr))); // divisor - cmp(rcx, 0); - je("div_divisor==0"); - - CodeGenerator::div(rcx); - mov(qword[rdi + offsetof(Registers, lo)], eax); - mov(qword[rdi + offsetof(Registers, hi)], edx); - jmp("div_exit"); - - L("div_divisor==0"); - mov(qword[rdi + offsetof(Registers, hi)], rax); - cmp(rax, 0); - jge("div_dividend>=0"); - mov(qword[rdi + offsetof(Registers, lo)], s64(1)); - L("div_dividend>=0"); - mov(qword[rdi + offsetof(Registers, lo)], s64(-1)); - - L("div_exit"); -} - -void JIT::divu(u32 instr) { - movsxd(rax, GPR(dword, RS(instr))); // dividend - movsxd(rcx, GPR(dword, RT(instr))); // divisor - cmp(rcx, 0); - je("divu_divisor==0"); - - CodeGenerator::div(rcx); - mov(qword[rdi + offsetof(Registers, lo)], eax); - mov(qword[rdi + offsetof(Registers, hi)], edx); - jmp("divu_exit"); - - L("divu_divisor==0"); - mov(qword[rdi + offsetof(Registers, hi)], rax); - mov(qword[rdi + offsetof(Registers, lo)], -1); - - L("divu_exit"); -} - -void JIT::ddiv(u32 instr) { - mov(rax, GPR(qword, RS(instr))); - mov(rcx, GPR(qword, RT(instr))); - mov(r8, 0x8000000000000000); - mov(r9, rax); - CodeGenerator::xor_(r9, r8); - mov(r8, 0xFFFFFFFFFFFFFFFF); - mov(r10, rcx); - CodeGenerator::xor_(r10, r8); - CodeGenerator::xor_(r9, r10); - cmp(rcx, 0); - je("ddiv_else_if"); - cmp(r9, 1); - jne("ddiv_else"); - mov(qword[rdi + offsetof(Registers, lo)], rax); - mov(qword[rdi + offsetof(Registers, hi)], 0); - jmp("ddiv_exit"); - L("ddiv_else_if"); - mov(qword[rdi + offsetof(Registers, hi)], rax); - cmp(rax, 0); - jge("ddiv_dividend>=0"); - mov(qword[rdi + offsetof(Registers, lo)], 1); - L("ddiv_dividend>=0"); - mov(qword[rdi + offsetof(Registers, lo)], -1); - L("ddiv_else"); - CodeGenerator::div(rcx); - mov(qword[rdi + offsetof(Registers, lo)], rax); - mov(qword[rdi + offsetof(Registers, hi)], rdx); - L("ddiv_exit"); -} - -void JIT::ddivu(u32 instr) { - mov(rax, GPR(qword, RS(instr))); - mov(rcx, GPR(qword, RT(instr))); - cmp(rcx, 0); - je("ddivu_divisor==0"); - CodeGenerator::div(rcx); - mov(qword[rdi + offsetof(Registers, lo)], rax); - mov(qword[rdi + offsetof(Registers, hi)], rdx); - jmp("ddivu_exit"); - L("ddivu_divisor==0"); - mov(qword[rdi + offsetof(Registers, lo)], -1); - mov(qword[rdi + offsetof(Registers, hi)], rax); - L("ddivu_exit"); -} - -void JIT::lui(u32 instr) { - u64 val = s64(s16(instr)); - val <<= 16; - mov(GPR(qword, RT(instr)), val); -} - -void JIT::lb(u32 instr) { - mov(rdx, GPR(qword, RS(instr))); - CodeGenerator::add(rdx, s64(s16(instr))); - mov(rsi, LOAD); - push(rcx); - lea(rcx, dword[rbp-4]); - emitCall(MapVAddr); - pop(rcx); - cmp(rax, 0); - je("lb_exception"); - mov(rsi, dword[rbp-4]); - push(rcx); - emitMemberCall(&Mem::Read, &mem); - pop(rcx); - mov(GPR(qword, RT(instr)), rax.cvt8()); - L("lb_exception"); - mov(rsi, rdx); - emitCall(HandleTLBException); - push(rsi); - mov(rdi, REG(byte, cop0.tlbError)); - mov(rsi, LOAD); - emitCall(GetTLBExceptionCode); - pop(rsi); - mov(rsi, rax); - mov(rdx, 0); - mov(rcx, 1); - emitCall(FireException); -} - -void JIT::lh(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; - if ((address & 0b1) > 0) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC); - return; - } - - u32 paddr = 0; - if(!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); - } else { - regs.gpr[RT(instr)] = (s16)mem.Read(regs, paddr); - } -} - -void JIT::lw(u32 instr) { - s16 offset = instr; - u64 address = regs.gpr[RS(instr)] + offset; - if (check_address_error(0b11, address)) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC); - return; - } - - u32 physical = 0; - if (!MapVAddr(regs, LOAD, address, physical)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); - } else { - regs.gpr[RT(instr)] = (s32)mem.Read(regs, physical); - } -} - -void JIT::ll(u32 instr) { - 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, regs.oldPC); - } else { - if ((address & 0b11) > 0) { - FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC); - return; - } else { - regs.gpr[RT(instr)] = (s32)mem.Read(regs, physical); - } - } - - regs.cop0.llbit = true; - regs.cop0.LLAddr = physical >> 4; -} - -void JIT::lwl(u32 instr) { - 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, regs.oldPC); - } else { - u32 shift = 8 * ((address ^ 0) & 3); - u32 mask = 0xFFFFFFFF << shift; - u32 data = mem.Read(regs, paddr & ~3); - s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data << shift)); - regs.gpr[RT(instr)] = result; - } -} - -void JIT::lwr(u32 instr) { - 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, regs.oldPC); - } else { - u32 shift = 8 * ((address ^ 3) & 3); - u32 mask = 0xFFFFFFFF >> shift; - u32 data = mem.Read(regs, paddr & ~3); - s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data >> shift)); - regs.gpr[RT(instr)] = result; - } -} - -void JIT::ld(u32 instr) { - s64 address = regs.gpr[RS(instr)] + (s16)instr; - if (check_address_error(0b111, address)) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC); - return; - } - - u32 paddr = 0; - if(!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); - } else { - s64 value = mem.Read(regs, paddr); - regs.gpr[RT(instr)] = value; - } -} - -void JIT::lld(u32 instr) { - if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) { - FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC); - 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, regs.oldPC); - } else { - if ((address & 0b111) > 0) { - FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC); - } else { - regs.gpr[RT(instr)] = mem.Read(regs, paddr); - regs.cop0.llbit = true; - regs.cop0.LLAddr = paddr >> 4; - } - } -} - -void JIT::ldl(u32 instr) { - 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, regs.oldPC); - } else { - s32 shift = 8 * ((address ^ 0) & 7); - u64 mask = 0xFFFFFFFFFFFFFFFF << shift; - u64 data = mem.Read(regs, paddr & ~7); - s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data << shift)); - regs.gpr[RT(instr)] = result; - } -} - -void JIT::ldr(u32 instr) { - 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, regs.oldPC); - } else { - s32 shift = 8 * ((address ^ 7) & 7); - u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; - u64 data = mem.Read(regs, paddr & ~7); - s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data >> shift)); - regs.gpr[RT(instr)] = result; - } -} - -void JIT::lbu(u32 instr) { - 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, regs.oldPC); - } else { - u8 value = mem.Read(regs, paddr); - regs.gpr[RT(instr)] = value; - } -} - -void JIT::lhu(u32 instr) { - s64 address = regs.gpr[RS(instr)] + (s16)instr; - if ((address & 0b1) > 0) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC); - return; - } - u32 paddr; - if (!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); - } else { - u16 value = mem.Read(regs, paddr); - regs.gpr[RT(instr)] = value; - } -} - -void JIT::lwu(u32 instr) { - s64 address = regs.gpr[RS(instr)] + (s16)instr; - if ((address & 0b11) > 0) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC); - return; - } - - u32 paddr; - if (!MapVAddr(regs, LOAD, address, paddr)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); - } else { - u32 value = mem.Read(regs, paddr); - regs.gpr[RT(instr)] = value; - } -} - -void JIT::sb(u32 instr) { - 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, regs.oldPC); - } else { - mem.Write(regs, paddr, regs.gpr[RT(instr)]); - } -} - -void JIT::sc(u32 instr) { - u64 address = regs.gpr[RS(instr)] + (s16)instr; - - if ((address & 0b11) > 0) { - FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC); - 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, regs.oldPC); - } else { - mem.Write(regs, paddr, regs.gpr[RT(instr)]); - regs.gpr[RT(instr)] = 1; - } - } else { - regs.gpr[RT(instr)] = 0; - } -} - -void JIT::scd(u32 instr) { - if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) { - FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC); - return; - } - - s64 address = regs.gpr[RS(instr)] + (s16)instr; - if ((address & 0b111) > 0) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC); - 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, regs.oldPC); - } else { - mem.Write(regs, paddr, regs.gpr[RT(instr)]); - regs.gpr[RT(instr)] = 1; - } - } else { - regs.gpr[RT(instr)] = 0; - } -} - -void JIT::sh(u32 instr) { - 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, regs.oldPC); - } else { - mem.Write(regs, physical, regs.gpr[RT(instr)]); - } -} - -void JIT::sw(u32 instr) { - s16 offset = instr; - u64 address = regs.gpr[RS(instr)] + offset; - if (check_address_error(0b11, address)) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC); - return; - } - - u32 physical; - if(!MapVAddr(regs, STORE, address, physical)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); - } else { - mem.Write(regs, physical, regs.gpr[RT(instr)]); - } -} - -void JIT::sd(u32 instr) { - s64 address = regs.gpr[RS(instr)] + (s16)instr; - if (check_address_error(0b111, address)) { - HandleTLBException(regs, address); - FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC); - return; - } - - u32 physical; - if(!MapVAddr(regs, STORE, address, physical)) { - HandleTLBException(regs, address); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); - } else { - mem.Write(regs, physical, regs.gpr[RT(instr)]); - } -} - -void JIT::sdl(u32 instr) { - 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, regs.oldPC); - } else { - s32 shift = 8 * ((address ^ 0) & 7); - u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; - u64 data = mem.Read(regs, paddr & ~7); - u64 rt = regs.gpr[RT(instr)]; - mem.Write(regs, paddr & ~7, (data & ~mask) | (rt >> shift)); - } -} - -void JIT::sdr(u32 instr) { - 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, regs.oldPC); - } else { - s32 shift = 8 * ((address ^ 7) & 7); - u64 mask = 0xFFFFFFFFFFFFFFFF << shift; - u64 data = mem.Read(regs, paddr & ~7); - u64 rt = regs.gpr[RT(instr)]; - mem.Write(regs, paddr & ~7, (data & ~mask) | (rt << shift)); - } -} - -void JIT::swl(u32 instr) { - 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, regs.oldPC); - } else { - u32 shift = 8 * ((address ^ 0) & 3); - u32 mask = 0xFFFFFFFF >> shift; - u32 data = mem.Read(regs, paddr & ~3); - u32 rt = regs.gpr[RT(instr)]; - mem.Write(regs, paddr & ~3, (data & ~mask) | (rt >> shift)); - } -} - -void JIT::swr(u32 instr) { - 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, regs.oldPC); - } else { - u32 shift = 8 * ((address ^ 3) & 3); - u32 mask = 0xFFFFFFFF << shift; - u32 data = mem.Read(regs, paddr & ~3); - u32 rt = regs.gpr[RT(instr)]; - mem.Write(regs, paddr & ~3, (data & ~mask) | (rt << shift)); - } -} - -void JIT::ori(u32 instr) { - s64 imm = (u16)instr; - mov(rax, GPR(qword, RS(instr))); - CodeGenerator::or_(rax, imm); - mov(GPR(qword, RT(instr)), rax); -} - -void JIT::or_(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rax, GPR(qword, RS(instr))); - mov(rcx, GPR(qword, RT(instr))); - CodeGenerator::or_(rax, rcx); - mov(GPR(qword, RD(instr)), rax); - } -} - -void JIT::nor(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rax, GPR(qword, RS(instr))); - mov(rcx, GPR(qword, RT(instr))); - CodeGenerator::or_(rax, rcx); - not_(rax); - mov(GPR(qword, RD(instr)), rax); - } -} - -void JIT::j(u32 instr) { - s32 target = (instr & 0x3ffffff) << 2; - s64 address = (regs.oldPC & ~0xfffffff) | target; - - mov(byte[rdi + offsetof(Registers, delaySlot)], 1); - mov(qword[rdi + offsetof(Registers, nextPC)], address); -} - -void JIT::jal(u32 instr) { - mov(rax, qword[rdi + offsetof(Registers, nextPC)]); - mov(GPR(qword, 31), rax); - j(instr); -} - -void JIT::jalr(u32 instr) { - mov(byte[rdi + offsetof(Registers, delaySlot)], 1); - mov(rax, GPR(qword, RS(instr))); - mov(qword[rdi + offsetof(Registers, nextPC)], rax); - - if (RD(instr) != 0) [[likely]] { - mov(rax, qword[rdi + offsetof(Registers, pc)]); - CodeGenerator::add(rax, 4); - mov(GPR(qword, RD(instr)), rax); - } -} - -void JIT::slti(u32 instr) { - mov(rax, s64(s16(instr))); - mov(rcx, GPR(qword, RS(instr))); - cmp(rcx, rax); - setl(GPR(qword, RT(instr))); -} - -void JIT::sltiu(u32 instr) { - mov(rax, s64(s16(instr))); - mov(rcx, GPR(qword, RS(instr))); - cmp(rcx, rax); - setb(GPR(qword, RT(instr))); -} - -void JIT::slt(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rax, GPR(qword, RS(instr))); - mov(rcx, GPR(qword, RT(instr))); - cmp(rax, rcx); - setl(GPR(qword, RD(instr))); - } -} - -void JIT::sltu(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rax, GPR(qword, RS(instr))); - mov(rcx, GPR(qword, RT(instr))); - cmp(rax, rcx); - setb(GPR(qword, RD(instr))); - } -} - -void JIT::xori(u32 instr) { - s64 imm = (u16)instr; - mov(rax, imm); - mov(rcx, GPR(qword, RS(instr))); - CodeGenerator::xor_(rcx, rax); - mov(GPR(qword, RT(instr)), rcx); -} - -void JIT::xor_(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rax, GPR(qword, RT(instr))); - mov(rcx, GPR(qword, RS(instr))); - CodeGenerator::xor_(rax, rcx); - mov(GPR(qword, RD(instr)), rax); - } -} - -void JIT::andi(u32 instr) { - s64 imm = (u16)instr; - mov(rax, (u16)instr); - mov(rcx, GPR(qword, RS(instr))); - CodeGenerator::and_(rcx, rax); - mov(GPR(qword, RT(instr)), rcx); -} - -void JIT::and_(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rax, GPR(qword, RT(instr))); - mov(rcx, GPR(qword, RS(instr))); - CodeGenerator::and_(rax, rcx); - mov(GPR(qword, RD(instr)), rax); - } -} - -void JIT::sll(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 sa = ((instr >> 6) & 0x1f); - mov(rax, GPR(qword, RT(instr))); - sal(rax, sa); - movsxd(rcx, eax); - mov(GPR(qword, RD(instr)), rcx); - } -} - -void JIT::sllv(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rcx, GPR(qword, RS(instr))); - CodeGenerator::and_(cl, 0x1F); - mov(rax, GPR(qword, RT(instr))); - sal(rax, cl); - movsxd(rcx, eax); - mov(GPR(qword, RD(instr)), rcx); - } -} - -void JIT::dsll32(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 sa = ((instr >> 6) & 0x1f) + 32; - mov(rax, GPR(qword, RT(instr))); - sal(rax, sa); - mov(GPR(qword, RT(instr)), rax); - } -} - -void JIT::dsll(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 sa = ((instr >> 6) & 0x1f); - mov(rax, GPR(qword, RT(instr))); - sal(rax, sa); - mov(GPR(qword, RT(instr)), rax); - } -} - -void JIT::dsllv(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rcx, GPR(qword, RS(instr))); - CodeGenerator::and_(cl, 63); - mov(rax, GPR(qword, RT(instr))); - sal(rax, cl); - mov(GPR(qword, RD(instr)), rax); - } -} - -void JIT::srl(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 sa = ((instr >> 6) & 0x1f); - mov(rax, GPR(qword, RT(instr))); - CodeGenerator::shr(rax, sa); - movsxd(rcx, eax); - mov(GPR(qword, RD(instr)), rcx); - } -} - -void JIT::srlv(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rcx, GPR(qword, RS(instr))); - CodeGenerator::and_(cl, 0x1F); - mov(rax, GPR(qword, RT(instr))); - shr(rax, cl); - movsxd(rcx, eax); - mov(GPR(qword, RD(instr)), rcx); - } -} - -void JIT::tgei(u32) { - -} - -void JIT::tgeiu(u32) { - -} - -void JIT::tlti(u32) { - -} - -void JIT::tltiu(u32) { - -} - -void JIT::teqi(u32) { - -} - -void JIT::tnei(u32) { - -} - -void JIT::tge(u32) { - -} - -void JIT::tgeu(u32) { - -} - -void JIT::tlt(u32) { - -} - -void JIT::tltu(u32) { - -} - -void JIT::teq(u32) { - -} - -void JIT::tne(u32) { - -} - -void JIT::dsrl(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 sa = ((instr >> 6) & 0x1f); - mov(rax, GPR(qword, RT(instr))); - CodeGenerator::shr(rax, sa); - mov(GPR(qword, RD(instr)), rax); - } -} - -void JIT::dsrlv(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rcx, GPR(qword, RS(instr))); - CodeGenerator::and_(cl, 63); - mov(rax, GPR(qword, RT(instr))); - shr(rax, cl); - mov(GPR(qword, RD(instr)), rax); - } -} - -void JIT::dsrl32(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 sa = ((instr >> 6) & 0x1f) + 32; - mov(rax, GPR(qword, RT(instr))); - CodeGenerator::shr(rax, sa); - mov(GPR(qword, RD(instr)), rax); - } -} - -void JIT::sra(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 sa = ((instr >> 6) & 0x1f); - mov(rax, GPR(qword, RT(instr))); - sar(rax, sa); - movsxd(rcx, eax); - mov(GPR(qword, RD(instr)), rcx); - } -} - -void JIT::srav(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rcx, GPR(qword, RS(instr))); - CodeGenerator::and_(cl, 0x1F); - mov(rax, GPR(qword, RT(instr))); - sar(rax, cl); - movsxd(rcx, eax); - mov(GPR(qword, RD(instr)), rcx); - } -} - -void JIT::dsra(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 sa = ((instr >> 6) & 0x1f); - mov(rax, GPR(qword, RT(instr))); - sar(rax, sa); - mov(GPR(qword, RD(instr)), rax); - } -} - -void JIT::dsrav(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rcx, GPR(qword, RS(instr))); - CodeGenerator::and_(cl, 63); - mov(rax, GPR(qword, RT(instr))); - sar(rax, cl); - mov(GPR(qword, RD(instr)), rax); - } -} - -void JIT::dsra32(u32 instr) { - if (RD(instr) != 0) [[likely]] { - u8 sa = ((instr >> 6) & 0x1f) + 32; - mov(rax, GPR(qword, RT(instr))); - sar(rax, sa); - mov(GPR(qword, RD(instr)), rax); - } -} - -void JIT::jr(u32 instr) { - mov(rax, GPR(qword, RS(instr))); - mov(REG(byte, delaySlot), 1); - mov(REG(qword, nextPC), rax); -} - -void JIT::dsub(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(rax, GPR(qword, RT(instr))); - mov(rcx, GPR(qword, RS(instr))); - CodeGenerator::sub(rcx, rax); - mov(GPR(qword, RD(instr)), rcx); - } -} - -void JIT::dsubu(u32 instr) { - dsub(instr); -} - -void JIT::sub(u32 instr) { - if (RD(instr) != 0) [[likely]] { - mov(eax, GPR(qword, RT(instr))); - mov(ecx, GPR(qword, RS(instr))); - CodeGenerator::sub(ecx, eax); - movsxd(rax, ecx); - mov(GPR(qword, RD(instr)), rax); - } -} - -void JIT::subu(u32 instr) { - sub(instr); -} - -void JIT::dmultu(u32 instr) { - 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 JIT::dmult(u32 instr) { - 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 JIT::multu(u32 instr) { - 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 JIT::mult(u32 instr) { - 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 JIT::mflo(u32 instr) { - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = regs.lo; - } -} - -void JIT::mfhi(u32 instr) { - if (RD(instr) != 0) [[likely]] { - regs.gpr[RD(instr)] = regs.hi; - } -} - -void JIT::mtlo(u32 instr) { - regs.lo = regs.gpr[RS(instr)]; -} - -void JIT::mthi(u32 instr) { - regs.hi = regs.gpr[RS(instr)]; -} - -void JIT::mtc2(u32 instr) { - -} - -void JIT::mfc2(u32 instr) { - -} - -void JIT::dmtc2(u32 instr) { - -} - -void JIT::dmfc2(u32 instr) { - -} - -void JIT::ctc2(u32) { - -} - -void JIT::cfc2(u32) { - -} - -} \ No newline at end of file diff --git a/src/backend/core/mem/Flash.cpp b/src/backend/core/mem/Flash.cpp index d6ff50f7..e0df02f2 100644 --- a/src/backend/core/mem/Flash.cpp +++ b/src/backend/core/mem/Flash.cpp @@ -49,7 +49,7 @@ void Flash::CommandExecute() { case FlashState::Erase: if(saveData.is_mapped()) { for (int i = 0; i < 128; i++) { - saveData[eraseOffs + i] = 0xFFi8; + saveData[eraseOffs + i] = 0xFF; } } else { Util::panic("Accessing flash when not mapped!"); diff --git a/src/backend/core/mmio/PIF.hpp b/src/backend/core/mmio/PIF.hpp index da45543e..54409216 100644 --- a/src/backend/core/mmio/PIF.hpp +++ b/src/backend/core/mmio/PIF.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace fs = std::filesystem; diff --git a/src/backend/core/registers/Cop1.cpp b/src/backend/core/registers/Cop1.cpp index 67fe5588..0e18e157 100644 --- a/src/backend/core/registers/Cop1.cpp +++ b/src/backend/core/registers/Cop1.cpp @@ -1,11 +1,9 @@ #include #include #include -#include #include namespace n64 { -using namespace Xbyak; Cop1::Cop1() { Reset(); } @@ -20,8 +18,6 @@ template void Cop1::decode(T& cpu, u32 instr) { if constexpr (std::is_same_v) { decodeInterp(cpu, instr); - } else if constexpr (std::is_same_v) { - decodeJIT(cpu, instr); } else { Util::panic("What the fuck did you just give me?!"); } @@ -152,157 +148,4 @@ void Cop1::decodeInterp(Interpreter &cpu, u32 instr) { default: Util::panic("Unimplemented COP1 instruction {} {}", mask_sub >> 3, mask_sub & 7); } } - -#ifdef REG -#undef REG -#define REG(ptr, member) cpu.ptr[cpu.rdi + offsetof(Registers, member)] -#endif - -void Cop1::decodeJIT(JIT &cpu, u32 instr) { - Registers ®s = cpu.regs; - if(!regs.cop0.status.cu1) { - FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true); - return; - } - - u8 mask_sub = (instr >> 21) & 0x1F; - u8 mask_fun = instr & 0x3F; - u8 mask_branch = (instr >> 16) & 0x1F; - switch(mask_sub) { - // 000r_rccc - case 0x00: mfc1(regs, instr); break; - case 0x01: dmfc1(regs, instr); break; - case 0x02: cfc1(regs, instr); break; - case 0x03: unimplemented(regs); break; - case 0x04: mtc1(regs, instr); break; - case 0x05: dmtc1(regs, instr); break; - case 0x06: ctc1(regs, instr); break; - case 0x07: unimplemented(regs); break; - case 0x08: - /*switch(mask_branch) { - case 0: { - cpu.mov(cpu.rax, REG(byte, cop1.fcr31.compare)); - cpu.b(instr, !regs.cop1.fcr31.compare); - } break; - case 1: { - cpu.b(instr, regs.cop1.fcr31.compare); - } break; - case 2: { - cpu.bl(instr, !regs.cop1.fcr31.compare); - } break; - case 3: { - cpu.bl(instr, regs.cop1.fcr31.compare); - } break; - default: Util::panic("Undefined BC COP1 {:02X}", mask_branch); - }*/ - break; - case 0x10: // s - switch(mask_fun) { - case 0x00: adds(regs, instr); break; - case 0x01: subs(regs, instr); break; - case 0x02: muls(regs, instr); break; - case 0x03: divs(regs, instr); break; - case 0x04: sqrts(regs, instr); break; - case 0x05: abss(regs, instr); break; - case 0x06: movs(regs, instr); break; - case 0x07: negs(regs, instr); break; - case 0x08: roundls(regs, instr); break; - case 0x09: truncls(regs, instr); break; - case 0x0A: ceills(regs, instr); break; - case 0x0B: floorls(regs, instr); break; - case 0x0C: roundws(regs, instr); break; - case 0x0D: truncws(regs, instr); break; - case 0x0E: ceilws(regs, instr); break; - case 0x0F: floorws(regs, instr); break; - case 0x20: - unimplemented(regs); - break; - case 0x21: cvtds(regs, instr); break; - case 0x24: cvtws(regs, instr); break; - case 0x25: cvtls(regs, instr); break; - case 0x30://ccond(regs, instr, F); break; - case 0x31://ccond(regs, instr, UN); break; - case 0x32://ccond(regs, instr, EQ); break; - case 0x33://ccond(regs, instr, UEQ); break; - case 0x34://ccond(regs, instr, OLT); break; - case 0x35://ccond(regs, instr, ULT); break; - case 0x36://ccond(regs, instr, OLE); break; - case 0x37://ccond(regs, instr, ULE); break; - case 0x38://ccond(regs, instr, SF); break; - case 0x39://ccond(regs, instr, NGLE); break; - case 0x3A://ccond(regs, instr, SEQ); break; - case 0x3B://ccond(regs, instr, NGL); break; - case 0x3C://ccond(regs, instr, LT); break; - case 0x3D://ccond(regs, instr, NGE); break; - case 0x3E://ccond(regs, instr, LE); break; - case 0x3F://ccond(regs, instr, NGT); 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: addd(regs, instr); break; - case 0x01: subd(regs, instr); break; - case 0x02: muld(regs, instr); break; - case 0x03: divd(regs, instr); break; - case 0x04: sqrtd(regs, instr); break; - case 0x05: absd(regs, instr); break; - case 0x06: movd(regs, instr); break; - case 0x07: negd(regs, instr); break; - case 0x08: roundld(regs, instr); break; - case 0x09: truncld(regs, instr); break; - case 0x0A: ceilld(regs, instr); break; - case 0x0B: floorld(regs, instr); break; - case 0x0C: roundwd(regs, instr); break; - case 0x0D: truncwd(regs, instr); break; - case 0x0E: ceilwd(regs, instr); break; - case 0x0F: floorwd(regs, instr); break; - case 0x20: cvtsd(regs, instr); break; - case 0x21: - unimplemented(regs); - break; - case 0x24: cvtwd(regs, instr); break; - case 0x25: cvtld(regs, instr); break; - case 0x30: //ccond(regs, instr, F); break; - case 0x31: //ccond(regs, instr, UN); break; - case 0x32: //ccond(regs, instr, EQ); break; - case 0x33: //ccond(regs, instr, UEQ); break; - case 0x34: //ccond(regs, instr, OLT); break; - case 0x35: //ccond(regs, instr, ULT); break; - case 0x36: //ccond(regs, instr, OLE); break; - case 0x37: //ccond(regs, instr, ULE); break; - case 0x38: //ccond(regs, instr, SF); break; - case 0x39: //ccond(regs, instr, NGLE); break; - case 0x3A: //ccond(regs, instr, SEQ); break; - case 0x3B: //ccond(regs, instr, NGL); break; - case 0x3C: //ccond(regs, instr, LT); break; - case 0x3D: //ccond(regs, instr, NGE); break; - case 0x3E: //ccond(regs, instr, LE); break; - case 0x3F: //ccond(regs, instr, NGT); 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 0x20: cvtsw(regs, instr); break; - case 0x21: cvtdw(regs, instr); break; - case 0x24: - unimplemented(regs); - break; - 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 0x20: cvtsl(regs, instr); break; - case 0x21: cvtdl(regs, instr); break; - case 0x24: case 0x25: - unimplemented(regs); - break; - 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); - } -} } \ No newline at end of file diff --git a/src/backend/core/registers/cop/cop1instructions.cpp b/src/backend/core/registers/cop/cop1instructions.cpp index 266d6aec..ea719dd9 100644 --- a/src/backend/core/registers/cop/cop1instructions.cpp +++ b/src/backend/core/registers/cop/cop1instructions.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include diff --git a/src/frontend/RenderWidget.cpp b/src/frontend/RenderWidget.cpp index 97e4d6e3..0fedee8f 100644 --- a/src/frontend/RenderWidget.cpp +++ b/src/frontend/RenderWidget.cpp @@ -2,10 +2,6 @@ #include RenderWidget::RenderWidget(QWidget* parent) : QWidget(parent) { - if (volkInitialize() != VK_SUCCESS) { - Util::panic("Could not initialize Vulkan loader!"); - } - create(); setAttribute(Qt::WA_NativeWindow); @@ -21,11 +17,14 @@ RenderWidget::RenderWidget(QWidget* parent) : QWidget(parent) { windowHandle()->setSurfaceType(QWindow::VulkanSurface); } - instance.create(); - windowHandle()->setVulkanInstance(&instance); + if(!Vulkan::Context::init_loader(nullptr)) { + Util::panic("Could not initialize Vulkan ICD"); + } + + windowHandle()->setVulkanInstance(&instance.get_qvkinstance()); wsiPlatform = new QtWSIPlatform(windowHandle()); windowInfo = std::make_unique(windowHandle()); - LoadWSIPlatform(wsiPlatform, std::move(windowInfo)); + LoadWSIPlatform(&instance, wsiPlatform, std::move(windowInfo)); } \ No newline at end of file diff --git a/src/frontend/RenderWidget.hpp b/src/frontend/RenderWidget.hpp index 262bbf4f..d7841121 100644 --- a/src/frontend/RenderWidget.hpp +++ b/src/frontend/RenderWidget.hpp @@ -5,11 +5,35 @@ #include #include +struct QtInstanceFactory : Vulkan::InstanceFactory { + VkInstance create_instance(const VkInstanceCreateInfo *info) override { + instance.setApiVersion({1,3,0}); + QByteArrayList exts; + for(int i = 0; i < info->enabledExtensionCount; i++) { + exts.push_back(QByteArray::fromStdString(info->ppEnabledExtensionNames[i])); + } + QByteArrayList layers; + for(int i = 0; i < info->enabledLayerCount; i++) { + layers.push_back(QByteArray::fromStdString(info->ppEnabledLayerNames[i])); + } + instance.setExtensions(exts); + instance.setLayers(layers); + instance.setApiVersion({1,3,0}); + instance.create(); + + return instance.vkInstance(); + } + + QVulkanInstance& get_qvkinstance() { return instance; } +private: + QVulkanInstance instance; +}; + class QtParallelRdpWindowInfo : public ParallelRdpWindowInfo { public: - QtParallelRdpWindowInfo(QWindow* window) : window(window) {} - CoordinatePair get_window_size() { - CoordinatePair{ static_cast(window->width()), static_cast(window->height()) }; + explicit QtParallelRdpWindowInfo(QWindow* window) : window(window) {} + CoordinatePair get_window_size() override { + return CoordinatePair{ static_cast(window->width()), static_cast(window->height()) }; } private: QWindow* window; @@ -17,7 +41,7 @@ private: class QtWSIPlatform final : public Vulkan::WSIPlatform { public: - QtWSIPlatform(QWindow* window) : window(window) {} + explicit QtWSIPlatform(QWindow* window) : window(window) {} std::vector get_instance_extensions() override { auto vec = std::vector(); @@ -29,7 +53,7 @@ public: return vec; } - VkSurfaceKHR create_surface(VkInstance, VkPhysicalDevice) override { + VkSurfaceKHR create_surface(VkInstance instance, VkPhysicalDevice) override { return QVulkanInstance::surfaceForWindow(window); } @@ -65,11 +89,11 @@ class RenderWidget : public QWidget { public: explicit RenderWidget(QWidget* parent); - QPaintEngine* paintEngine() const override { + [[nodiscard]] QPaintEngine* paintEngine() const override { return nullptr; } private: std::unique_ptr windowInfo; QtWSIPlatform* wsiPlatform; - QVulkanInstance instance; + QtInstanceFactory instance; }; \ No newline at end of file