diff --git a/src/backend/Core.hpp b/src/backend/Core.hpp index 6597f113..c7656fb6 100644 --- a/src/backend/Core.hpp +++ b/src/backend/Core.hpp @@ -24,6 +24,7 @@ struct Core { VI& GetVI() { return mem.mmio.vi; } void CpuReset() { + cpuDynarec.Reset(); regs.Reset(); } diff --git a/src/backend/core/Dynarec.cpp b/src/backend/core/Dynarec.cpp index 3d021333..3beb5ec7 100644 --- a/src/backend/core/Dynarec.cpp +++ b/src/backend/core/Dynarec.cpp @@ -6,47 +6,66 @@ namespace n64::JIT { namespace fs = std::filesystem; Dynarec::~Dynarec() { - dumpCode.close(); + std::free(codeCache); } -Dynarec::Dynarec() : code(DEFAULT_MAX_CODE_SIZE, AutoGrow) { - if(fs::exists("jit.dump")) { - fs::remove("jit.dump"); - } - - dumpCode.open("jit.dump", std::ios::app | std::ios::binary); - code.ready(); +Dynarec::Dynarec() : code(CODECACHE_SIZE, codeCache) { + codeCache = (u8*)Util::aligned_alloc(4096, CODECACHE_SIZE); + CodeArray::protect( + codeCache, + CODECACHE_SIZE, + CodeArray::PROTECT_RWE + ); } -void Dynarec::Recompile(Registers& regs, Mem& mem) { +void Dynarec::Recompile(Registers& regs, Mem& mem, u32 pc) { bool branch = false, prevBranch = false; - u32 start_addr = regs.pc; + u32 startPC = pc; + u32 loopPC = pc; Fn block = code.getCurr(); + if(code.getSize() >= CODECACHE_SIZE) { + Util::print("Code cache overflow!\n"); + code.setSize(code.getSize() & (CODECACHE_SIZE - 1)); + InvalidateCache(); + } + + Util::print("Start of block @ PC {:08X}\n", loopPC); code.sub(rsp, 8); while(!prevBranch) { instrInBlock++; prevBranch = branch; - u32 instr = mem.Read32(regs, start_addr, start_addr); - - start_addr += 4; + u32 instr = mem.Read32(regs, loopPC, loopPC); code.mov(rdi, (u64)®s); + + Util::print("\tInstr: {:08X}, PC: {:08X}\n", instr, loopPC); + code.mov(r8, qword[rdi + REG_OFFSET(oldPC)]); + code.mov(r9, qword[rdi + REG_OFFSET(pc)]); + code.mov(r10, qword[rdi + REG_OFFSET(nextPC)]); + code.mov(r8, r9); + code.mov(r9, r10); + code.add(r10, 4); + code.mov(qword[rdi + REG_OFFSET(oldPC)], r8); + code.mov(qword[rdi + REG_OFFSET(pc)], r9); + code.mov(qword[rdi + REG_OFFSET(nextPC)], r10); + + loopPC += 4; + branch = Exec(regs, mem, instr); } code.add(rsp, 8); code.ret(); - dumpCode.write(code.getCode(), code.getSize()); - u32 pc = regs.pc & 0xffffffff; - codeCache[pc >> 20][pc & 0xFFF] = block; - block(); + Util::print("End of block @ PC {:08X}, len: {}\n", loopPC, instrInBlock); + + blockCache[startPC >> 20][startPC & 0xFFF] = block; + blockCache[startPC >> 20][startPC & 0xFFF](); } -void Dynarec::AllocateOuter(Registers& regs) { - u32 pc = regs.pc & 0xffffffff; - codeCache[pc >> 20] = (Fn*)calloc(0xFFF, sizeof(Fn)); +void Dynarec::AllocateOuter(u32 pc) { + blockCache[pc >> 20] = (Fn*)bumpAlloc(0x1000 * sizeof(Fn)); } int Dynarec::Step(Mem &mem, Registers& regs) { @@ -55,17 +74,20 @@ int Dynarec::Step(Mem &mem, Registers& regs) { regs.prevDelaySlot = regs.delaySlot; regs.delaySlot = false; - u32 pc = regs.pc & 0xffffffff; + u32 pc{}; + if(!MapVAddr(regs, LOAD, regs.pc, pc)) { + Util::panic("[RECOMPILER] Failed to translate PC to physical address (v: {:08X})\n", regs.pc); + } - if(codeCache[pc >> 20]) { - if(codeCache[pc >> 20][pc & 0xfff]) { - codeCache[pc >> 20][pc & 0xfff](); + if(blockCache[pc >> 20]) { + if(blockCache[pc >> 20][pc & 0xfff]) { + blockCache[pc >> 20][pc & 0xfff](); } else { - Recompile(regs, mem); + Recompile(regs, mem, pc); } } else { - AllocateOuter(regs); - Recompile(regs, mem); + AllocateOuter(pc); + Recompile(regs, mem, pc); } return instrInBlock; diff --git a/src/backend/core/Dynarec.hpp b/src/backend/core/Dynarec.hpp index 2d220426..f8380ae1 100644 --- a/src/backend/core/Dynarec.hpp +++ b/src/backend/core/Dynarec.hpp @@ -10,6 +10,7 @@ using Fn = void (*)(); #define GPR_OFFSET(x) ((uintptr_t)®s.gpr[(x)] - (uintptr_t)®s) #define REG_OFFSET(kind) ((uintptr_t)®s.kind - (uintptr_t)®s) +#define CODECACHE_SIZE (2 << 25) struct Dynarec { Dynarec(); @@ -17,17 +18,30 @@ struct Dynarec { int Step(Mem&, n64::Registers&); void Reset() { code.reset(); + InvalidateCache(); } u64 cop2Latch{}; CodeGenerator code; + void InvalidatePage(u32); + void InvalidateCache(); private: friend struct Cop1; - Fn* codeCache[0x80000]{}; + Fn* blockCache[0x80000]{}; + u8* codeCache; int instrInBlock = 0; - std::ofstream dumpCode; + bool enableBreakpoints = false; + u64 sizeUsed = 0; - void Recompile(n64::Registers&, Mem&); - void AllocateOuter(n64::Registers&); + inline void emitBreakpoint() { + #ifndef NDEBUG + if(enableBreakpoints) + code.int3(); + #endif + } + + void* bumpAlloc(u64 size, u8 val = 0); + void Recompile(n64::Registers&, Mem&, u32 pc); + void AllocateOuter(u32 pc); void cop2Decode(n64::Registers&, u32); bool special(n64::Registers&, u32); bool regimm(n64::Registers&, u32); diff --git a/src/backend/core/Mem.cpp b/src/backend/core/Mem.cpp index 03489461..c651df2c 100644 --- a/src/backend/core/Mem.cpp +++ b/src/backend/core/Mem.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include namespace n64 { @@ -279,6 +280,246 @@ template u32 Mem::Read32(n64::Registers ®s, u64 vaddr, s64 pc); template u64 Mem::Read64(n64::Registers ®s, u64 vaddr, s64 pc); template u64 Mem::Read64(n64::Registers ®s, u64 vaddr, s64 pc); +template +void Mem::Write8(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u32 val, s64 pc) { + u32 paddr = vaddr; + if (!MapVAddr(regs, LOAD, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false); + } + + dyn.InvalidatePage(paddr); + + const auto page = paddr >> 12; + auto offset = paddr & 0xFFF; + const auto pointer = readPages[page]; + + if(pointer) { + if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) { + val = val << (8 * (3 - (paddr & 3))); + offset = (offset & DMEM_DSIZE) & ~3; + } + + ((u8*)pointer)[BYTE_ADDRESS(offset)] = val; + } else { + switch (paddr) { + case 0x00000000 ... 0x007FFFFF: + mmio.rdp.rdram[BYTE_ADDRESS(paddr)] = val; + break; + case 0x04000000 ... 0x0403FFFF: + val = val << (8 * (3 - (paddr & 3))); + paddr = (paddr & DMEM_DSIZE) & ~3; + if (paddr & 0x1000) + Util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); + else + Util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); + break; + case 0x04040000 ... 0x040FFFFF: + case 0x04100000 ... 0x041FFFFF: + case 0x04300000 ... 0x044FFFFF: + case 0x04500000 ... 0x048FFFFF: + Util::panic("MMIO Write8!\n"); + case 0x10000000 ... 0x13FFFFFF: + break; + case 0x1FC007C0 ... 0x1FC007FF: + val = val << (8 * (3 - (paddr & 3))); + paddr = (paddr - 0x1FC007C0) & ~3; + Util::WriteAccess(pifRam, paddr, htobe32(val)); + ProcessPIFCommands(pifRam, mmio.si.controller, *this); + break; + case 0x00800000 ... 0x03FFFFFF: + case 0x04200000 ... 0x042FFFFF: + case 0x08000000 ... 0x0FFFFFFF: + case 0x04900000 ... 0x07FFFFFF: + case 0x1FC00800 ... 0x7FFFFFFF: + case 0x80000000 ... 0xFFFFFFFF: + break; + default: + Util::panic("Unimplemented 8-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val, + (u64) regs.pc); + } + } +} + +template +void Mem::Write16(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u32 val, s64 pc) { + u32 paddr = vaddr; + if (!MapVAddr(regs, STORE, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, false); + } + + dyn.InvalidatePage(paddr); + + const auto page = paddr >> 12; + auto offset = paddr & 0xFFF; + const auto pointer = readPages[page]; + + if(pointer) { + if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) { + val = val << (16 * !(paddr & 2)); + offset &= ~3; + } + + Util::WriteAccess((u8*)pointer, HALF_ADDRESS(offset), val); + } else { + switch (paddr) { + case 0x00000000 ... 0x007FFFFF: + Util::WriteAccess(mmio.rdp.rdram.data(), HALF_ADDRESS(paddr), val); + break; + case 0x04000000 ... 0x0403FFFF: + val = val << (16 * !(paddr & 2)); + paddr &= ~3; + if (paddr & 0x1000) + Util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); + else + Util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); + break; + case 0x04040000 ... 0x040FFFFF: + case 0x04100000 ... 0x041FFFFF: + case 0x04300000 ... 0x044FFFFF: + case 0x04500000 ... 0x048FFFFF: + Util::panic("MMIO Write16!\n"); + case 0x10000000 ... 0x13FFFFFF: + break; + case 0x1FC007C0 ... 0x1FC007FF: + val = val << (16 * !(paddr & 2)); + paddr &= ~3; + Util::WriteAccess(pifRam, paddr - 0x1FC007C0, htobe32(val)); + ProcessPIFCommands(pifRam, mmio.si.controller, *this); + break; + case 0x00800000 ... 0x03FFFFFF: + case 0x04200000 ... 0x042FFFFF: + case 0x08000000 ... 0x0FFFFFFF: + case 0x04900000 ... 0x07FFFFFF: + case 0x1FC00800 ... 0x7FFFFFFF: + case 0x80000000 ... 0xFFFFFFFF: + break; + default: + Util::panic("Unimplemented 16-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val, + (u64) regs.pc); + } + } +} + +template +void Mem::Write32(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u32 val, s64 pc) { + u32 paddr = vaddr; + if(!MapVAddr(regs, STORE, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, false); + } + + dyn.InvalidatePage(paddr); + + const auto page = paddr >> 12; + auto offset = paddr & 0xFFF; + const auto pointer = readPages[page]; + + if(pointer) { + Util::WriteAccess((u8*)pointer, offset, val); + } else { + switch(paddr) { + case 0x00000000 ... 0x007FFFFF: + Util::WriteAccess(mmio.rdp.rdram.data(), paddr, val); + break; + case 0x04000000 ... 0x0403FFFF: + if(paddr & 0x1000) + Util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); + else + Util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); + break; + case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: + case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: mmio.Write(*this, regs, paddr, val); break; + case 0x10000000 ... 0x13FF0013: break; + case 0x13FF0014: { + if(val < ISVIEWER_SIZE) { + char* message = (char*)calloc(val + 1, 1); + memcpy(message, isviewer, val); + fmt::print("{}", message); + free(message); + } + } break; + case 0x13FF0020 ... 0x13FFFFFF: + Util::WriteAccess(isviewer, paddr - 0x13FF0020, htobe32(val)); + break; + case 0x1FC007C0 ... 0x1FC007FF: + Util::WriteAccess(pifRam, paddr - 0x1FC007C0, htobe32(val)); + ProcessPIFCommands(pifRam, mmio.si.controller, *this); + break; + case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: + case 0x08000000 ... 0x0FFFFFFF: case 0x04900000 ... 0x07FFFFFF: + case 0x1FC00800 ... 0x7FFFFFFF: case 0x80000000 ... 0xFFFFFFFF: break; + default: Util::panic("Unimplemented 32-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val, (u64)regs.pc); + } + } +} + +template +void Mem::Write64(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u64 val, s64 pc) { + u32 paddr = vaddr; + if(!MapVAddr(regs, STORE, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, false); + } + + dyn.InvalidatePage(paddr); + + const auto page = paddr >> 12; + auto offset = paddr & 0xFFF; + const auto pointer = readPages[page]; + + if(pointer) { + if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) { + val >>= 32; + } + Util::WriteAccess((u8*)pointer, offset, val); + } else { + switch (paddr) { + case 0x00000000 ... 0x007FFFFF: + Util::WriteAccess(mmio.rdp.rdram.data(), paddr, val); + break; + case 0x04000000 ... 0x0403FFFF: + val >>= 32; + if (paddr & 0x1000) + Util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); + else + Util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); + break; + case 0x04040000 ... 0x040FFFFF: + case 0x04100000 ... 0x041FFFFF: + case 0x04300000 ... 0x044FFFFF: + case 0x04500000 ... 0x048FFFFF: + Util::panic("MMIO Write64!\n"); + case 0x10000000 ... 0x13FFFFFF: + break; + case 0x1FC007C0 ... 0x1FC007FF: + Util::WriteAccess(pifRam, paddr - 0x1FC007C0, htobe64(val)); + ProcessPIFCommands(pifRam, mmio.si.controller, *this); + break; + case 0x00800000 ... 0x03FFFFFF: + case 0x04200000 ... 0x042FFFFF: + case 0x08000000 ... 0x0FFFFFFF: + case 0x04900000 ... 0x07FFFFFF: + case 0x1FC00800 ... 0x7FFFFFFF: + case 0x80000000 ... 0xFFFFFFFF: + break; + default: + Util::panic("Unimplemented 64-bit write at address {:08X} with value {:0X} (PC = {:016X})\n", paddr, val, + (u64) regs.pc); + } + } +} + +template void Mem::Write8(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc); +template void Mem::Write8(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc); +template void Mem::Write16(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc); +template void Mem::Write16(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc); +template void Mem::Write32(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc); +template void Mem::Write32(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc); +template void Mem::Write64(Registers& regs, JIT::Dynarec&, u64 vaddr, u64 val, s64 pc); +template void Mem::Write64(Registers& regs, JIT::Dynarec&, u64 vaddr, u64 val, s64 pc); + template void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) { u32 paddr = vaddr; diff --git a/src/backend/core/Mem.hpp b/src/backend/core/Mem.hpp index fea7ca7c..b12b9906 100644 --- a/src/backend/core/Mem.hpp +++ b/src/backend/core/Mem.hpp @@ -15,6 +15,10 @@ struct CartInfo { u32 crc; }; +namespace JIT { +struct Dynarec; +} + struct Mem { ~Mem() = default; Mem(); @@ -33,6 +37,14 @@ struct Mem { template u64 Read64(Registers&, u64, s64); template + void Write8(Registers&, JIT::Dynarec&, u64, u32, s64); + template + void Write16(Registers&, JIT::Dynarec&, u64, u32, s64); + template + void Write32(Registers&, JIT::Dynarec&, u64, u32, s64); + template + void Write64(Registers&, JIT::Dynarec&, u64, u64, s64); + template void Write8(Registers&, u64, u32, s64); template void Write16(Registers&, u64, u32, s64); diff --git a/src/backend/core/dynarec/MemoryManagement.cpp b/src/backend/core/dynarec/MemoryManagement.cpp new file mode 100644 index 00000000..a4431d2c --- /dev/null +++ b/src/backend/core/dynarec/MemoryManagement.cpp @@ -0,0 +1,27 @@ +#include + +namespace n64::JIT { +void Dynarec::InvalidatePage(u32 paddr) { + blockCache[paddr >> 20] = nullptr; +} + +void Dynarec::InvalidateCache() { + sizeUsed = 0; + for(int i = 0; i < 0x80000; i++) { + blockCache[i] = nullptr; + } +} + +void* Dynarec::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/dynarec/decode.cpp b/src/backend/core/dynarec/decode.cpp index 9957d4fe..edc45f4c 100644 --- a/src/backend/core/dynarec/decode.cpp +++ b/src/backend/core/dynarec/decode.cpp @@ -82,7 +82,7 @@ bool Dynarec::special(n64::Registers& regs, u32 instr) { code.call(rax); res = true; break; - case 0x0C: Util::panic("[RECOMPILER] Unhandled syscall instruction {:016X}\n", (u64)regs.pc); + case 0x0C: Util::print("[RECOMPILER] Unhandled syscall instruction {:016X}\n", (u64)regs.pc); /*dumpCode.close();*/ exit(1); case 0x0D: Util::panic("[RECOMPILER] Unhandled break instruction {:016X}\n", (u64)regs.pc); case 0x0F: break; // SYNC case 0x10: @@ -526,6 +526,7 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { code.call(rax); break; case 0x09: + emitBreakpoint(); code.mov(rsi, (u64)instr); code.mov(rax, (u64)addiu); code.call(rax); @@ -674,43 +675,50 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { break; case 0x28: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, (u64)this); + code.mov(rcx, (u64)instr); code.mov(rax, (u64)sb); code.call(rax); break; case 0x29: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, (u64)this); + code.mov(rcx, (u64)instr); code.mov(rax, (u64)sh); code.call(rax); break; case 0x2A: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, (u64)this); + code.mov(rcx, (u64)instr); code.mov(rax, (u64)swl); code.call(rax); break; case 0x2B: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, (u64)this); + code.mov(rcx, (u64)instr); code.mov(rax, (u64)sw); code.call(rax); break; case 0x2C: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, (u64)this); + code.mov(rcx, (u64)instr); code.mov(rax, (u64)sdl); code.call(rax); break; case 0x2D: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, (u64)this); + code.mov(rcx, (u64)instr); code.mov(rax, (u64)sdr); code.call(rax); break; case 0x2E: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, (u64)this); + code.mov(rcx, (u64)instr); code.mov(rax, (u64)swr); code.call(rax); break; @@ -747,7 +755,8 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { break; case 0x38: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, (u64)this); + code.mov(rcx, (u64)instr); code.mov(rax, (u64)sc); code.call(rax); break; @@ -759,7 +768,8 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { break; case 0x3C: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, (u64)this); + code.mov(rcx, (u64)instr); code.mov(rax, (u64)scd); code.call(rax); break; @@ -771,7 +781,8 @@ bool Dynarec::Exec(n64::Registers& regs, Mem& mem, u32 instr) { break; case 0x3F: code.mov(rsi, (u64)&mem); - code.mov(rdx, (u64)instr); + code.mov(rdx, (u64)this); + code.mov(rcx, (u64)instr); code.mov(rax, (u64)sd); code.call(rax); break; diff --git a/src/backend/core/dynarec/instructions.cpp b/src/backend/core/dynarec/instructions.cpp index b72036f9..c3766f28 100644 --- a/src/backend/core/dynarec/instructions.cpp +++ b/src/backend/core/dynarec/instructions.cpp @@ -148,14 +148,14 @@ void ddivu(Registers& regs, u32 instr) { void branch(Registers& regs, bool cond, s64 address) { regs.delaySlot = true; if (cond) { - regs.pc = address; + regs.nextPC = address; } } void branch_likely(Registers& regs, bool cond, s64 address) { regs.delaySlot = true; if (cond) { - regs.pc = address; + regs.nextPC = address; } else { regs.SetPC(regs.nextPC); } @@ -357,12 +357,12 @@ void lwu(Registers& regs, Mem& mem, u32 instr) { regs.gpr[RT(instr)] = value; } -void sb(Registers& regs, Mem& mem, u32 instr) { +void sb(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { u32 address = regs.gpr[RS(instr)] + (s16)instr; - mem.Write8(regs, address, regs.gpr[RT(instr)], regs.oldPC); + mem.Write8(regs, dyn, address, regs.gpr[RT(instr)], regs.oldPC); } -void sc(Registers& regs, Mem& mem, u32 instr) { +void sc(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b11)) { HandleTLBException(regs, address); @@ -370,14 +370,14 @@ void sc(Registers& regs, Mem& mem, u32 instr) { } if(regs.cop0.llbit) { - mem.Write32(regs, address, regs.gpr[RT(instr)], regs.oldPC); + mem.Write32(regs, dyn, address, regs.gpr[RT(instr)], regs.oldPC); } regs.gpr[RT(instr)] = (u64)regs.cop0.llbit; regs.cop0.llbit = false; } -void scd(Registers& regs, Mem& mem, u32 instr) { +void scd(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b111)) { HandleTLBException(regs, address); @@ -386,14 +386,14 @@ void scd(Registers& regs, Mem& mem, u32 instr) { } if(regs.cop0.llbit) { - mem.Write64(regs, address, regs.gpr[RT(instr)], regs.oldPC); + mem.Write64(regs, dyn, address, regs.gpr[RT(instr)], regs.oldPC); } regs.gpr[RT(instr)] = (s64)((u64)regs.cop0.llbit); regs.cop0.llbit = false; } -void sh(Registers& regs, Mem& mem, u32 instr) { +void sh(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b1)) { HandleTLBException(regs, address); @@ -406,11 +406,11 @@ void sh(Registers& regs, Mem& mem, u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); } else { - mem.Write16(regs, physical, regs.gpr[RT(instr)], regs.oldPC); + mem.Write16(regs, dyn, physical, regs.gpr[RT(instr)], regs.oldPC); } } -void sw(Registers& regs, Mem& mem, u32 instr) { +void sw(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { s16 offset = instr; u64 address = regs.gpr[RS(instr)] + offset; if (check_address_error(address, 0b11)) { @@ -424,11 +424,11 @@ void sw(Registers& regs, Mem& mem, u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); } else { - mem.Write32(regs, physical, regs.gpr[RT(instr)], regs.oldPC); + mem.Write32(regs, dyn, physical, regs.gpr[RT(instr)], regs.oldPC); } } -void sd(Registers& regs, Mem& mem, u32 instr) { +void sd(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { s64 address = regs.gpr[RS(instr)] + (s16)instr; if (check_address_error(address, 0b11)) { HandleTLBException(regs, address); @@ -441,12 +441,12 @@ void sd(Registers& regs, Mem& mem, u32 instr) { HandleTLBException(regs, address); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true); } else { - mem.Write64(regs, physical, regs.gpr[RT(instr)], regs.oldPC); + mem.Write64(regs, dyn, physical, regs.gpr[RT(instr)], regs.oldPC); } } -void sdl(Registers& regs, Mem& mem, u32 instr) { +void sdl(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, STORE, address, paddr)) { @@ -457,11 +457,11 @@ void sdl(Registers& regs, Mem& mem, u32 instr) { u64 mask = 0xFFFFFFFFFFFFFFFF >> shift; u64 data = mem.Read64(regs, paddr & ~7, regs.oldPC); u64 rt = regs.gpr[RT(instr)]; - mem.Write64(regs, paddr & ~7, (data & ~mask) | (rt >> shift), regs.oldPC); + mem.Write64(regs, dyn, paddr & ~7, (data & ~mask) | (rt >> shift), regs.oldPC); } } -void sdr(Registers& regs, Mem& mem, u32 instr) { +void sdr(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, STORE, address, paddr)) { @@ -472,11 +472,11 @@ void sdr(Registers& regs, Mem& mem, u32 instr) { u64 mask = 0xFFFFFFFFFFFFFFFF << shift; u64 data = mem.Read64(regs, paddr & ~7, regs.oldPC); u64 rt = regs.gpr[RT(instr)]; - mem.Write64(regs, paddr & ~7, (data & ~mask) | (rt << shift), regs.oldPC); + mem.Write64(regs, dyn, paddr & ~7, (data & ~mask) | (rt << shift), regs.oldPC); } } -void swl(Registers& regs, Mem& mem, u32 instr) { +void swl(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, STORE, address, paddr)) { @@ -487,11 +487,11 @@ void swl(Registers& regs, Mem& mem, u32 instr) { u32 mask = 0xFFFFFFFF >> shift; u32 data = mem.Read32(regs, paddr & ~3, regs.oldPC); u32 rt = regs.gpr[RT(instr)]; - mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt >> shift), regs.oldPC); + mem.Write32(regs, dyn, paddr & ~3, (data & ~mask) | (rt >> shift), regs.oldPC); } } -void swr(Registers& regs, Mem& mem, u32 instr) { +void swr(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) { u64 address = regs.gpr[RS(instr)] + (s16)instr; u32 paddr; if (!MapVAddr(regs, STORE, address, paddr)) { @@ -502,7 +502,7 @@ void swr(Registers& regs, Mem& mem, u32 instr) { u32 mask = 0xFFFFFFFF << shift; u32 data = mem.Read32(regs, paddr & ~3, regs.oldPC); u32 rt = regs.gpr[RT(instr)]; - mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt << shift), regs.oldPC); + mem.Write32(regs, dyn, paddr & ~3, (data & ~mask) | (rt << shift), regs.oldPC); } } diff --git a/src/backend/core/dynarec/instructions.hpp b/src/backend/core/dynarec/instructions.hpp index 246a00f5..9829900e 100644 --- a/src/backend/core/dynarec/instructions.hpp +++ b/src/backend/core/dynarec/instructions.hpp @@ -60,16 +60,16 @@ void multu(Registers&, u32); void mthi(Registers&, u32); void mtlo(Registers&, u32); void nor(Registers&, u32); -void sb(Registers&, Mem&, u32); -void sc(Registers&, Mem&, u32); -void scd(Registers&, Mem&, u32); -void sd(Registers&, Mem&, u32); -void sdl(Registers&, Mem&, u32); -void sdr(Registers&, Mem&, u32); -void sh(Registers&, Mem&, u32); -void sw(Registers&, Mem&, u32); -void swl(Registers&, Mem&, u32); -void swr(Registers&, Mem&, u32); +void sb(Registers&, Mem&, Dynarec&, u32); +void sc(Registers&, Mem&, Dynarec&, u32); +void scd(Registers&, Mem&, Dynarec&, u32); +void sd(Registers&, Mem&, Dynarec&, u32); +void sdl(Registers&, Mem&, Dynarec&, u32); +void sdr(Registers&, Mem&, Dynarec&, u32); +void sh(Registers&, Mem&, Dynarec&, u32); +void sw(Registers&, Mem&, Dynarec&, u32); +void swl(Registers&, Mem&, Dynarec&, u32); +void swr(Registers&, Mem&, Dynarec&, u32); void slti(Registers&, u32); void sltiu(Registers&, u32); void slt(Registers&, u32); diff --git a/src/utils/MemoryHelpers.hpp b/src/utils/MemoryHelpers.hpp index f3556a71..71bb3d97 100644 --- a/src/utils/MemoryHelpers.hpp +++ b/src/utils/MemoryHelpers.hpp @@ -85,4 +85,22 @@ inline u32 crc32(u32 crc, const u8 *buf, size_t len) { } return ~crc; } + +#ifdef _WIN32 +inline void* aligned_alloc(size_t alignment, size_t size) { + return _aligned_malloc(size, alignment); +} + +inline void free(void* ptr) { + _aligned_free(ptr); +} +#else +inline void* aligned_alloc(size_t alignment, size_t size) { + return std::aligned_alloc(alignment, size); +} + +inline void free(void* ptr) { + std::free(ptr); +} +#endif } \ No newline at end of file diff --git a/src/utils/log.hpp b/src/utils/log.hpp index 07d90f18..8d45f096 100644 --- a/src/utils/log.hpp +++ b/src/utils/log.hpp @@ -13,7 +13,6 @@ constexpr void print(const std::string& fmt, Args... args) { #ifndef _WIN32 if constexpr(messageType == Error) { fmt::print(fmt::emphasis::bold | fg(fmt::color::red), fmt, args...); - exit(-1); } else if constexpr(messageType == Warn) { fmt::print(fg(fmt::color::yellow), fmt, args...); } else if constexpr(messageType == Info) { @@ -24,10 +23,7 @@ constexpr void print(const std::string& fmt, Args... args) { #endif } #else - if constexpr(messageType == Error) { - fmt::print(fmt, args...); - exit(-1); - } else if constexpr(messageType == Debug) { + if constexpr(messageType == Debug) { #ifndef NDEBUG fmt::print(fmt, args...); #endif @@ -40,6 +36,7 @@ constexpr void print(const std::string& fmt, Args... args) { template constexpr void panic(const std::string& fmt, Args... args) { print(fmt, args...); + exit(-1); } template