diff --git a/Core/MIPS/x86/CompFPU.cpp b/Core/MIPS/x86/CompFPU.cpp index 68df48e328..1a60b6d611 100644 --- a/Core/MIPS/x86/CompFPU.cpp +++ b/Core/MIPS/x86/CompFPU.cpp @@ -96,222 +96,46 @@ void Jit::Comp_FPULS(u32 op) switch(op >> 26) { case 49: //FI(ft) = Memory::Read_U32(addr); break; //lwc1 - gpr.Lock(rs); - fpr.SpillLock(ft); - fpr.BindToRegister(ft, false, true); - - if (gpr.R(rs).IsImm()) { - void *data = Memory::GetPointer(gpr.R(rs).GetImmValue() + offset); - if (data) + gpr.Lock(rs); + fpr.SpillLock(ft); + fpr.BindToRegister(ft, false, true); + + JitSafeMem safe(this, rs, offset); + OpArg src; + if (safe.PrepareRead(src, (void *) &Memory::Read_U32)) + MOVSS(fpr.RX(ft), src); + if (safe.PrepareSlowRead((void *) &Memory::Read_U32)) { -#ifdef _M_IX86 - MOVSS(fpr.RX(ft), M(data)); -#else - MOVSS(fpr.RX(ft), MDisp(RBX, gpr.R(rs).GetImmValue() + offset)); -#endif - } - else - { - MOV(32, R(EAX), Imm32(gpr.R(rs).GetImmValue() + offset)); - ABI_CallFunctionA(thunks.ProtectFunction((void *) &Memory::Read_U32, 1), R(EAX)); MOV(32, M((void *)&ssLoadStoreTemp), R(EAX)); MOVSS(fpr.RX(ft), M((void *)&ssLoadStoreTemp)); - - // Should we check the core state? - if (!g_Config.bIgnoreBadMemAccess) - { - CMP(32, M((void*)&coreState), Imm32(0)); - FixupBranch skip2 = J_CC(CC_E); - MOV(32, M(¤tMIPS->pc), Imm32(js.compilerPC + 4)); - WriteSyscallExit(); - SetJumpTarget(skip2); - } } + safe.WriteFinish(); + + gpr.UnlockAll(); + fpr.ReleaseSpillLocks(); } - else - { - // We may not even need to move into EAX as a temporary. - X64Reg addr; - if (gpr.R(rs).IsSimpleReg()) - { - // TODO: Maybe just add a check if it's away, don't mind copying to EAX instead... - gpr.BindToRegister(rs, true, false); - addr = gpr.RX(rs); - } - else - { - MOV(32, R(EAX), gpr.R(rs)); - addr = EAX; - } - - if (!g_Config.bFastMemory) - { - // Is it in physical ram? - CMP(32, R(addr), Imm32(0x08000000)); - FixupBranch tooLow = J_CC(CC_L); - CMP(32, R(addr), Imm32(0x0A000000)); - FixupBranch tooHigh = J_CC(CC_GE); - - const u8* safe = GetCodePtr(); -#ifdef _M_IX86 - MOVSS(fpr.RX(ft), MDisp(addr, (u32)Memory::base + offset)); -#else - MOVSS(fpr.RX(ft), MComplex(RBX, addr, SCALE_1, offset)); -#endif - - FixupBranch skip = J(); - SetJumpTarget(tooLow); - SetJumpTarget(tooHigh); - - // Might also be the scratchpad. - CMP(32, R(addr), Imm32(0x00010000)); - FixupBranch tooLow2 = J_CC(CC_L); - CMP(32, R(addr), Imm32(0x00014000)); - J_CC(CC_L, safe); - SetJumpTarget(tooLow2); - - LEA(32, EAX, MDisp(addr, offset)); - ABI_CallFunctionA(thunks.ProtectFunction((void *) &Memory::Read_U32, 1), R(EAX)); - MOV(32, M((void *)&ssLoadStoreTemp), R(EAX)); - MOVSS(fpr.RX(ft), M((void *)&ssLoadStoreTemp)); - - // Should we check the core state? - if (!g_Config.bIgnoreBadMemAccess) - { - CMP(32, M((void*)&coreState), Imm32(0)); - FixupBranch skip2 = J_CC(CC_E); - MOV(32, M(¤tMIPS->pc), Imm32(js.compilerPC + 4)); - WriteSyscallExit(); - SetJumpTarget(skip2); - } - - SetJumpTarget(skip); - } - else - { -#ifdef _M_IX86 - // Need to modify it, too bad. - if (addr != EAX) - MOV(32, R(EAX), gpr.R(rs)); - AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); - MOVSS(fpr.RX(ft), MDisp(EAX, (u32)Memory::base + offset)); -#else - MOVSS(fpr.RX(ft), MComplex(RBX, addr, SCALE_1, offset)); -#endif - } - } - - gpr.UnlockAll(); - fpr.ReleaseSpillLocks(); break; case 57: //Memory::Write_U32(FI(ft), addr); break; //swc1 - gpr.Lock(rs); - fpr.SpillLock(ft); - fpr.BindToRegister(ft, true, false); - - if (gpr.R(rs).IsImm()) { - void *data = Memory::GetPointer(gpr.R(rs).GetImmValue() + offset); - if (data) + gpr.Lock(rs); + fpr.SpillLock(ft); + fpr.BindToRegister(ft, true, false); + + JitSafeMem safe(this, rs, offset); + OpArg dest; + if (safe.PrepareWrite(dest)) + MOVSS(dest, fpr.RX(ft)); + if (safe.PrepareSlowWrite()) { -#ifdef _M_IX86 - MOVSS(M(data), fpr.RX(ft)); -#else - MOVSS(MDisp(RBX, gpr.R(rs).GetImmValue() + offset), fpr.RX(ft)); -#endif - } - else - { - MOV(32, R(EAX), Imm32(gpr.R(rs).GetImmValue() + offset)); MOVSS(M((void *)&ssLoadStoreTemp), fpr.RX(ft)); - ABI_CallFunctionAA(thunks.ProtectFunction((void *) &Memory::Write_U32, 2), M((void *)&ssLoadStoreTemp), R(EAX)); - - // Should we check the core state? - if (!g_Config.bIgnoreBadMemAccess) - { - CMP(32, M((void*)&coreState), Imm32(0)); - FixupBranch skip2 = J_CC(CC_E); - MOV(32, M(¤tMIPS->pc), Imm32(js.compilerPC + 4)); - WriteSyscallExit(); - SetJumpTarget(skip2); - } + safe.DoSlowWrite((void *) &Memory::Write_U32, M((void *)&ssLoadStoreTemp)); } + safe.WriteFinish(); + + gpr.UnlockAll(); + fpr.ReleaseSpillLocks(); } - else - { - // We may not even need to move into EAX as a temporary. - X64Reg addr; - if (gpr.R(rs).IsSimpleReg()) - { - // TODO: Maybe just add a check if it's away, don't mind copying to EAX instead... - gpr.BindToRegister(rs, true, false); - addr = gpr.RX(rs); - } - else - { - MOV(32, R(EAX), gpr.R(rs)); - addr = EAX; - } - - if (!g_Config.bFastMemory) - { - // Is it in physical ram? - CMP(32, R(addr), Imm32(0x08000000)); - FixupBranch tooLow = J_CC(CC_L); - CMP(32, R(addr), Imm32(0x0A000000)); - FixupBranch tooHigh = J_CC(CC_GE); - - const u8* safe = GetCodePtr(); -#ifdef _M_IX86 - MOVSS(MDisp(addr, (u32)Memory::base + offset), fpr.RX(ft)); -#else - MOVSS(MComplex(RBX, addr, SCALE_1, offset), fpr.RX(ft)); -#endif - - FixupBranch skip = J(); - SetJumpTarget(tooLow); - SetJumpTarget(tooHigh); - - // Might also be the scratchpad. - CMP(32, R(addr), Imm32(0x00010000)); - FixupBranch tooLow2 = J_CC(CC_L); - CMP(32, R(addr), Imm32(0x00014000)); - J_CC(CC_L, safe); - SetJumpTarget(tooLow2); - - LEA(32, EAX, MDisp(addr, offset)); - MOVSS(M((void *)&ssLoadStoreTemp), fpr.RX(ft)); - ABI_CallFunctionAA(thunks.ProtectFunction((void *) &Memory::Write_U32, 2), M((void *)&ssLoadStoreTemp), R(EAX)); - - // Should we check the core state? - if (!g_Config.bIgnoreBadMemAccess) - { - CMP(32, M((void*)&coreState), Imm32(0)); - FixupBranch skip2 = J_CC(CC_E); - MOV(32, M(¤tMIPS->pc), Imm32(js.compilerPC + 4)); - WriteSyscallExit(); - SetJumpTarget(skip2); - } - - SetJumpTarget(skip); - } - else - { -#ifdef _M_IX86 - // Need to modify it, too bad. - if (addr != EAX) - MOV(32, R(EAX), gpr.R(rs)); - AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); - MOVSS(MDisp(EAX, (u32)Memory::base + offset), fpr.RX(ft)); -#else - MOVSS(MComplex(RBX, addr, SCALE_1, offset), fpr.RX(ft)); -#endif - } - } - - gpr.UnlockAll(); - fpr.ReleaseSpillLocks(); break; default: diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index 2dcead88cd..799a884f4f 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -51,106 +51,13 @@ namespace MIPSComp gpr.Lock(rt, rs); gpr.BindToRegister(rt, rt == rs, true); - if (gpr.R(rs).IsImm()) - { - void *data = Memory::GetPointer(gpr.R(rs).GetImmValue() + offset); - if (data) - { -#ifdef _M_IX86 - (this->*mov)(32, bits, gpr.RX(rt), M(data)); -#else - (this->*mov)(32, bits, gpr.RX(rt), MDisp(RBX, gpr.R(rs).GetImmValue() + offset)); -#endif - } - else - { - MOV(32, R(EAX), Imm32(gpr.R(rs).GetImmValue() + offset)); - ABI_CallFunctionA(thunks.ProtectFunction(safeFunc, 1), R(EAX)); - (this->*mov)(32, bits, gpr.RX(rt), R(EAX)); - - // Should we check the core state? - if (!g_Config.bIgnoreBadMemAccess) - { - CMP(32, M((void*)&coreState), Imm32(0)); - FixupBranch skip2 = J_CC(CC_E); - MOV(32, M(¤tMIPS->pc), Imm32(js.compilerPC + 4)); - WriteSyscallExit(); - SetJumpTarget(skip2); - } - } - } - else - { - // We may not even need to move into EAX as a temporary. - X64Reg addr; - if (gpr.R(rs).IsSimpleReg()) - { - // TODO: Maybe just add a check if it's away, don't mind copying to EAX instead... - if (rs != rt) - gpr.BindToRegister(rs, true, false); - addr = gpr.RX(rs); - } - else - { - MOV(32, R(EAX), gpr.R(rs)); - addr = EAX; - } - - if (!g_Config.bFastMemory) - { - // Is it in physical ram? - CMP(32, R(addr), Imm32(0x08000000)); - FixupBranch tooLow = J_CC(CC_L); - CMP(32, R(addr), Imm32(0x0A000000)); - FixupBranch tooHigh = J_CC(CC_GE); - - const u8* safe = GetCodePtr(); -#ifdef _M_IX86 - (this->*mov)(32, bits, gpr.RX(rt), MDisp(addr, (u32)Memory::base + offset)); -#else - (this->*mov)(32, bits, gpr.RX(rt), MComplex(RBX, addr, SCALE_1, offset)); -#endif - - FixupBranch skip = J(); - SetJumpTarget(tooLow); - SetJumpTarget(tooHigh); - - // Might also be the scratchpad. - CMP(32, R(addr), Imm32(0x00010000)); - FixupBranch tooLow2 = J_CC(CC_L); - CMP(32, R(addr), Imm32(0x00014000)); - J_CC(CC_L, safe); - SetJumpTarget(tooLow2); - - LEA(32, EAX, MDisp(addr, offset)); - ABI_CallFunctionA(thunks.ProtectFunction(safeFunc, 1), R(EAX)); - (this->*mov)(32, bits, gpr.RX(rt), R(EAX)); - - // Should we check the core state? - if (!g_Config.bIgnoreBadMemAccess) - { - CMP(32, M((void*)&coreState), Imm32(0)); - FixupBranch skip2 = J_CC(CC_E); - MOV(32, M(¤tMIPS->pc), Imm32(js.compilerPC + 4)); - WriteSyscallExit(); - SetJumpTarget(skip2); - } - - SetJumpTarget(skip); - } - else - { -#ifdef _M_IX86 - // Need to modify it, too bad. - if (addr != EAX) - MOV(32, R(EAX), gpr.R(rs)); - AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); - (this->*mov)(32, bits, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset)); -#else - (this->*mov)(32, bits, gpr.RX(rt), MComplex(RBX, addr, SCALE_1, offset)); -#endif - } - } + JitSafeMem safe(this, rs, offset); + OpArg src; + if (safe.PrepareRead(src, safeFunc)) + (this->*mov)(32, bits, gpr.RX(rt), src); + if (safe.PrepareSlowRead(safeFunc)) + (this->*mov)(32, bits, gpr.RX(rt), R(EAX)); + safe.WriteFinish(); gpr.UnlockAll(); } @@ -170,129 +77,28 @@ namespace MIPSComp const bool needSwap = bits == 8 && !gpr.R(rt).IsSimpleReg(EDX) && !gpr.R(rt).IsSimpleReg(ECX); if (needSwap) gpr.FlushLockX(EDX); +#else + const bool needSwap = false; #endif - if (gpr.R(rs).IsImm()) + JitSafeMem safe(this, rs, offset); + OpArg dest; + if (safe.PrepareWrite(dest)) { - void *data = Memory::GetPointer(gpr.R(rs).GetImmValue() + offset); - if (data) + if (needSwap) { -#ifdef _M_IX86 - if (needSwap) - { - MOV(32, R(EDX), gpr.R(rt)); - MOV(bits, M(data), R(EDX)); - } - else - MOV(bits, M(data), gpr.R(rt)); -#else - MOV(bits, MDisp(RBX, gpr.R(rs).GetImmValue() + offset), gpr.R(rt)); -#endif + MOV(32, R(EDX), gpr.R(rt)); + MOV(bits, dest, R(EDX)); } else - { - MOV(32, R(EAX), Imm32(gpr.R(rs).GetImmValue() + offset)); - ABI_CallFunctionAA(thunks.ProtectFunction(safeFunc, 2), gpr.R(rt), R(EAX)); - - // Should we check the core state? - if (!g_Config.bIgnoreBadMemAccess) - { - CMP(32, M((void*)&coreState), Imm32(0)); - FixupBranch skip2 = J_CC(CC_E); - MOV(32, M(¤tMIPS->pc), Imm32(js.compilerPC + 4)); - WriteSyscallExit(); - SetJumpTarget(skip2); - } - } + MOV(bits, dest, gpr.R(rt)); } - else - { - // We may not even need to move into EAX as a temporary. - X64Reg addr; - if (gpr.R(rs).IsSimpleReg()) - { - // TODO: Maybe just add a check if it's away, don't mind copying to EAX instead... - if (rs != rt) - gpr.BindToRegister(rs, true, false); - addr = gpr.RX(rs); - } - else - { - MOV(32, R(EAX), gpr.R(rs)); - addr = EAX; - } + if (safe.PrepareSlowWrite()) + safe.DoSlowWrite(safeFunc, gpr.R(rt)); + safe.WriteFinish(); - if (!g_Config.bFastMemory) - { - // Is it in physical ram? - CMP(32, R(addr), Imm32(0x08000000)); - FixupBranch tooLow = J_CC(CC_L); - CMP(32, R(addr), Imm32(0x0A000000)); - FixupBranch tooHigh = J_CC(CC_GE); - - const u8* safe = GetCodePtr(); -#ifdef _M_IX86 - if (needSwap) - { - MOV(32, R(EDX), gpr.R(rt)); - MOV(bits, MDisp(addr, (u32)Memory::base + offset), R(EDX)); - } - else - MOV(bits, MDisp(addr, (u32)Memory::base + offset), gpr.R(rt)); -#else - MOV(bits, MComplex(RBX, addr, SCALE_1, offset), gpr.R(rt)); -#endif - - FixupBranch skip = J(); - SetJumpTarget(tooLow); - SetJumpTarget(tooHigh); - - // Might also be the scratchpad. - CMP(32, R(addr), Imm32(0x00010000)); - FixupBranch tooLow2 = J_CC(CC_L); - CMP(32, R(addr), Imm32(0x00014000)); - J_CC(CC_L, safe); - SetJumpTarget(tooLow2); - - LEA(32, EAX, MDisp(addr, offset)); - ABI_CallFunctionAA(thunks.ProtectFunction(safeFunc, 2), gpr.R(rt), R(EAX)); - - // Should we check the core state? - if (!g_Config.bIgnoreBadMemAccess) - { - CMP(32, M((void*)&coreState), Imm32(0)); - FixupBranch skip2 = J_CC(CC_E); - MOV(32, M(¤tMIPS->pc), Imm32(js.compilerPC + 4)); - WriteSyscallExit(); - SetJumpTarget(skip2); - } - - SetJumpTarget(skip); - } - else - { -#ifdef _M_IX86 - // Need to modify it, too bad. - if (addr != EAX) - MOV(32, R(EAX), gpr.R(rs)); - AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); - if (needSwap) - { - MOV(32, R(EDX), gpr.R(rt)); - MOV(bits, MDisp(EAX, (u32)Memory::base + offset), R(EDX)); - } - else - MOV(bits, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt)); -#else - MOV(bits, MComplex(RBX, addr, SCALE_1, offset), gpr.R(rt)); -#endif - } - } - -#ifdef _M_IX86 if (needSwap) gpr.UnlockAllX(); -#endif gpr.UnlockAll(); } diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index 3134d5cbae..a09d3dc22c 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -19,6 +19,7 @@ #include #include "../../Core.h" #include "../../CoreTiming.h" +#include "../../Config.h" #include "../MIPS.h" #include "../MIPSCodeUtils.h" #include "../MIPSInt.h" @@ -301,4 +302,197 @@ bool Jit::CheckJitBreakpoint(u32 addr, int downcountOffset) return false; } +Jit::JitSafeMem::JitSafeMem(Jit *jit, int raddr, s32 offset) + : jit_(jit), raddr_(raddr), offset_(offset), needsCheck_(false), needsSkip_(false) +{ +} + +bool Jit::JitSafeMem::PrepareWrite(OpArg &dest) +{ + // If it's an immediate, we can do the write if valid. + if (jit_->gpr.IsImmediate(raddr_)) + { + u32 addr = jit_->gpr.GetImmediate32(raddr_) + offset_; + if (Memory::IsValidAddress(addr)) + { +#ifdef _M_IX86 + dest = M(Memory::base + addr); +#else + dest = MDisp(RBX, addr); +#endif + return true; + } + else + return false; + } + // Otherwise, we always can do the write (conditionally.) + else + dest = PrepareMemoryOpArg(); + return true; +} + +bool Jit::JitSafeMem::PrepareRead(OpArg &src, void *safeFunc) +{ + if (jit_->gpr.IsImmediate(raddr_)) + { + u32 addr = jit_->gpr.GetImmediate32(raddr_) + offset_; + if (Memory::IsValidAddress(addr)) + { +#ifdef _M_IX86 + src = M(Memory::base + addr); +#else + src = MDisp(RBX, addr); +#endif + return true; + } + else + return false; + } + else + src = PrepareMemoryOpArg(); + return true; +} + +OpArg Jit::JitSafeMem::PrepareMemoryOpArg() +{ + // We may not even need to move into EAX as a temporary. + // TODO: Except on x86 in fastmem mode. + if (jit_->gpr.R(raddr_).IsSimpleReg()) + { + jit_->gpr.BindToRegister(raddr_, true, false); + xaddr_ = jit_->gpr.RX(raddr_); + } + else + { + jit_->MOV(32, R(EAX), jit_->gpr.R(raddr_)); + xaddr_ = EAX; + } + + X64Reg xaddrResult = xaddr_; + if (!g_Config.bFastMemory) + { + // Is it in physical ram? + jit_->CMP(32, R(xaddr_), Imm32(PSP_GetKernelMemoryBase())); + tooLow_ = jit_->J_CC(CC_L); + jit_->CMP(32, R(xaddr_), Imm32(PSP_GetUserMemoryEnd())); + tooHigh_ = jit_->J_CC(CC_GE); + + // We may need to jump back up here. + safe_ = jit_->GetCodePtr(); + } + else + { +#ifdef _M_IX86 + // Need to modify it, too bad. + if (xaddr_ != EAX) + jit_->MOV(32, R(EAX), R(xaddr_)); + jit_->AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); + xaddrResult = EAX; +#endif + } + +#ifdef _M_IX86 + return MDisp(xaddrResult, (u32) Memory::base + offset_); +#else + return MComplex(RBX, xaddrResult, SCALE_1, offset_); +#endif +} + +void Jit::JitSafeMem::PrepareSlowAccess() +{ + // Skip the fast path (which the caller wrote just now.) + skip_ = jit_->J(); + needsSkip_ = true; + jit_->SetJumpTarget(tooLow_); + jit_->SetJumpTarget(tooHigh_); + + // Might also be the scratchpad. + jit_->CMP(32, R(xaddr_), Imm32(PSP_GetScratchpadMemoryBase())); + FixupBranch tooLow = jit_->J_CC(CC_L); + jit_->CMP(32, R(xaddr_), Imm32(PSP_GetScratchpadMemoryEnd())); + jit_->J_CC(CC_L, safe_); + jit_->SetJumpTarget(tooLow); +} + +bool Jit::JitSafeMem::PrepareSlowWrite() +{ + // If it's immediate, we only need a slow write on invalid. + if (jit_->gpr.IsImmediate(raddr_)) + { + u32 addr = jit_->gpr.GetImmediate32(raddr_) + offset_; + return !g_Config.bFastMemory && !Memory::IsValidAddress(addr); + } + + if (!g_Config.bFastMemory) + { + PrepareSlowAccess(); + return true; + } + else + return false; +} + +void Jit::JitSafeMem::DoSlowWrite(void *safeFunc, const OpArg src) +{ + if (jit_->gpr.IsImmediate(raddr_)) + { + u32 addr = jit_->gpr.GetImmediate32(raddr_) + offset_; + jit_->MOV(32, R(EAX), Imm32(addr)); + } + else + jit_->LEA(32, EAX, MDisp(xaddr_, offset_)); + + jit_->ABI_CallFunctionAA(jit_->thunks.ProtectFunction(safeFunc, 2), src, R(EAX)); + needsCheck_ = true; +} + +bool Jit::JitSafeMem::PrepareSlowRead(void *safeFunc) +{ + if (jit_->gpr.IsImmediate(raddr_)) + { + u32 addr = jit_->gpr.GetImmediate32(raddr_) + offset_; + if (!g_Config.bFastMemory) + { + jit_->MOV(32, R(EAX), Imm32(addr)); + jit_->ABI_CallFunctionA(jit_->thunks.ProtectFunction(safeFunc, 1), R(EAX)); + needsCheck_ = true; + return true; + } + // Can't read a bad immediate in fast memory mode. + else + return false; + } + + if (!g_Config.bFastMemory) + { + PrepareSlowAccess(); + + jit_->LEA(32, EAX, MDisp(xaddr_, offset_)); + jit_->ABI_CallFunctionA(jit_->thunks.ProtectFunction(safeFunc, 1), R(EAX)); + needsCheck_ = true; + + return true; + } + else + return false; +} + +void Jit::JitSafeMem::WriteFinish() +{ + if (needsCheck_) + { + // Memory::Read_U32/etc. may have tripped coreState. + if (!g_Config.bIgnoreBadMemAccess) + { + jit_->CMP(32, M((void*)&coreState), Imm32(0)); + FixupBranch skipCheck = jit_->J_CC(CC_E); + jit_->MOV(32, M(¤tMIPS->pc), Imm32(jit_->js.compilerPC + 4)); + jit_->WriteSyscallExit(); + jit_->SetJumpTarget(skipCheck); + } + } + if (needsSkip_) + jit_->SetJumpTarget(skip_); +} + } // namespace diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 620fa64e5a..1b499b8a5a 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -183,6 +183,41 @@ private: ThunkManager thunks; MIPSState *mips_; + + class JitSafeMem + { + public: + JitSafeMem(Jit *jit, int raddr, s32 offset); + + // Emit code necessary for a memory write, returns true if MOV to dest is needed. + bool PrepareWrite(OpArg &dest); + // Emit code proceeding a slow write call, returns true if slow write is needed. + bool PrepareSlowWrite(); + // Emit a slow write from src. + void DoSlowWrite(void *safeFunc, const OpArg src); + + // Emit code necessary for a memory read, returns true if MOV from src is needed. + bool PrepareRead(OpArg &src, void *safeFunc); + // Emit code for a slow read call, and returns true if result is in EAX. + bool PrepareSlowRead(void *safeFunc); + + // Cleans up final code for the memory access. + void WriteFinish(); + + private: + OpArg PrepareMemoryOpArg(); + void PrepareSlowAccess(); + + Jit *jit_; + int raddr_; + s32 offset_; + bool needsCheck_; + bool needsSkip_; + X64Reg xaddr_; + FixupBranch tooLow_, tooHigh_, skip_; + const u8 *safe_; + }; + friend class JitSafeMem; }; typedef void (Jit::*MIPSCompileFunc)(u32 opcode); diff --git a/Core/MemMap.h b/Core/MemMap.h index 0c92469880..bf77692018 100644 --- a/Core/MemMap.h +++ b/Core/MemMap.h @@ -55,6 +55,8 @@ typedef void (*readFn16)(u16&, const u32); typedef void (*readFn32)(u32&, const u32); typedef void (*readFn64)(u64&, const u32); +inline u32 PSP_GetScratchpadMemoryBase() { return 0x00010000;} +inline u32 PSP_GetScratchpadMemoryEnd() { return 0x00014000;} inline u32 PSP_GetKernelMemoryBase() { return 0x08000000;} inline u32 PSP_GetKernelMemoryEnd() { return 0x08400000;}