diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 4825bd980f..97db741b4e 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -347,8 +347,8 @@ void Jit::Comp_SVQ(u32 op) } safe.Finish(); - fpr.ReleaseSpillLocks(); gpr.UnlockAll(); + fpr.ReleaseSpillLocks(); } break; diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index acb3d73fdc..48aba1ed00 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -469,8 +469,8 @@ 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) +Jit::JitSafeMem::JitSafeMem(Jit *jit, int raddr, s32 offset, u32 alignMask) + : jit_(jit), raddr_(raddr), offset_(offset), needsCheck_(false), needsSkip_(false), alignMask_(alignMask) { // This makes it more instructions, so let's play it safe and say we need a far jump. far_ = !g_Config.bIgnoreBadMemAccess || !CBreakPoints::GetMemChecks().empty(); @@ -497,9 +497,9 @@ bool Jit::JitSafeMem::PrepareWrite(OpArg &dest, int size) MemCheckImm(MEM_WRITE); #ifdef _M_IX86 - dest = M(Memory::base + (iaddr_ & Memory::MEMVIEW32_MASK)); + dest = M(Memory::base + (iaddr_ & Memory::MEMVIEW32_MASK & alignMask_)); #else - dest = MDisp(RBX, iaddr_); + dest = MDisp(RBX, iaddr_ & alignMask_); #endif return true; } @@ -522,9 +522,9 @@ bool Jit::JitSafeMem::PrepareRead(OpArg &src, int size) MemCheckImm(MEM_READ); #ifdef _M_IX86 - src = M(Memory::base + (iaddr_ & Memory::MEMVIEW32_MASK)); + src = M(Memory::base + (iaddr_ & Memory::MEMVIEW32_MASK & alignMask_)); #else - src = MDisp(RBX, iaddr_); + src = MDisp(RBX, iaddr_ & alignMask_); #endif return true; } @@ -540,7 +540,7 @@ OpArg Jit::JitSafeMem::NextFastAddress(int suboffset) { if (jit_->gpr.IsImmediate(raddr_)) { - u32 addr = jit_->gpr.GetImmediate32(raddr_) + offset_ + suboffset; + u32 addr = (jit_->gpr.GetImmediate32(raddr_) + offset_ + suboffset) & alignMask_; #ifdef _M_IX86 return M(Memory::base + (addr & Memory::MEMVIEW32_MASK)); @@ -549,6 +549,8 @@ OpArg Jit::JitSafeMem::NextFastAddress(int suboffset) #endif } + _dbg_assert_msg_(HLE, (suboffset 0xFFFFFFFF) == suboffset, "suboffset must be aligned"); + #ifdef _M_IX86 return MDisp(xaddr_, (u32) Memory::base + offset_ + suboffset); #else @@ -559,8 +561,13 @@ OpArg Jit::JitSafeMem::NextFastAddress(int suboffset) OpArg Jit::JitSafeMem::PrepareMemoryOpArg(ReadType type) { // 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()) + bool needTemp = alignMask_ != 0xFFFFFFFF; +#ifdef _M_IX86 + // We always mask on 32 bit in fast memory mode. + needTemp = needTemp || g_Config.bFastMemory; +#endif + + if (jit_->gpr.R(raddr_).IsSimpleReg() && !needTemp) { jit_->gpr.BindToRegister(raddr_, true, false); xaddr_ = jit_->gpr.RX(raddr_); @@ -587,18 +594,24 @@ OpArg Jit::JitSafeMem::PrepareMemoryOpArg(ReadType type) 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)); - xaddr_ = EAX; #endif } + // TODO: This could be more optimal, but the common case is that we want xaddr_ not to include offset_. + // Since we need to align them after add, we add and subtract. + if (alignMask_ != 0xFFFFFFFF) + { + jit_->ADD(32, R(xaddr_), Imm32(offset_)); + jit_->AND(32, R(xaddr_), Imm32(alignMask_)); + jit_->SUB(32, R(xaddr_), Imm32(offset_)); + } + + #ifdef _M_IX86 - return MDisp(xaddr_, (u32) Memory::base + offset_); + return MDisp(xaddr_, (u32) Memory::base + offset_); #else - return MComplex(RBX, xaddr_, SCALE_1, offset_); + return MComplex(RBX, xaddr_, SCALE_1, offset_); #endif } @@ -636,9 +649,13 @@ bool Jit::JitSafeMem::PrepareSlowWrite() void Jit::JitSafeMem::DoSlowWrite(void *safeFunc, const OpArg src, int suboffset) { if (iaddr_ != (u32) -1) - jit_->MOV(32, R(EAX), Imm32(iaddr_ + suboffset)); + jit_->MOV(32, R(EAX), Imm32((iaddr_ + suboffset) & alignMask_)); else + { jit_->LEA(32, EAX, MDisp(xaddr_, offset_ + suboffset)); + if (alignMask_ != 0xFFFFFFFF) + jit_->AND(32, R(EAX), Imm32(alignMask_)); + } jit_->ABI_CallFunctionAA(jit_->thunks.ProtectFunction(safeFunc, 2), src, R(EAX)); needsCheck_ = true; @@ -653,12 +670,14 @@ bool Jit::JitSafeMem::PrepareSlowRead(void *safeFunc) // No slow read necessary. if (ImmValid()) return false; - jit_->MOV(32, R(EAX), Imm32(iaddr_)); + jit_->MOV(32, R(EAX), Imm32(iaddr_ & alignMask_)); } else { PrepareSlowAccess(); jit_->LEA(32, EAX, MDisp(xaddr_, offset_)); + if (alignMask_ != 0xFFFFFFFF) + jit_->AND(32, R(EAX), Imm32(alignMask_)); } jit_->ABI_CallFunctionA(jit_->thunks.ProtectFunction(safeFunc, 1), R(EAX)); @@ -679,13 +698,17 @@ void Jit::JitSafeMem::NextSlowRead(void *safeFunc, int suboffset) if (jit_->gpr.IsImmediate(raddr_)) { - _dbg_assert_msg_(JIT, !Memory::IsValidAddress(iaddr_ + suboffset), "NextSlowRead() for a valid immediate address?"); + _dbg_assert_msg_(JIT, !Memory::IsValidAddress(iaddr_ + suboffset), "NextSlowRead() for an invalid immediate address?"); - jit_->MOV(32, R(EAX), Imm32(iaddr_ + suboffset)); + jit_->MOV(32, R(EAX), Imm32((iaddr_ + suboffset) & alignMask_)); } // For GPR, if xaddr_ was the dest register, this will be wrong. Don't use in GPR. else + { jit_->LEA(32, EAX, MDisp(xaddr_, offset_ + suboffset)); + if (alignMask_ != 0xFFFFFFFF) + jit_->AND(32, R(EAX), Imm32(alignMask_)); + } jit_->ABI_CallFunctionA(jit_->thunks.ProtectFunction(safeFunc, 1), R(EAX)); } diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 47546c1ea8..cef15def15 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -292,7 +292,7 @@ private: class JitSafeMem { public: - JitSafeMem(Jit *jit, int raddr, s32 offset); + JitSafeMem(Jit *jit, int raddr, s32 offset, u32 alignMask = 0xFFFFFFFF); // Emit code necessary for a memory write, returns true if MOV to dest is needed. bool PrepareWrite(OpArg &dest, int size); @@ -336,6 +336,7 @@ private: bool needsCheck_; bool needsSkip_; bool far_; + u32 alignMask_; u32 iaddr_; X64Reg xaddr_; FixupBranch tooLow_, tooHigh_, skip_;