From 662ae772141237ce99b65e88a8b7de4090820f09 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 6 Jul 2013 00:54:53 -0700 Subject: [PATCH] Save regs before/after 3-arg func calls on x86. This fixes bugs only on x64 when ABI_CallFunctionACC and etc. were used. This was breaking things since R8 was not being saved (arg 3.) --- Common/ABI.cpp | 1 + Common/Thunk.h | 8 ++++++++ Core/MIPS/x86/Jit.cpp | 43 +++++++++++++++++++++++++++++++++++-------- Core/MIPS/x86/Jit.h | 5 +++++ 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/Common/ABI.cpp b/Common/ABI.cpp index bf683b6fe4..75185cc7ab 100644 --- a/Common/ABI.cpp +++ b/Common/ABI.cpp @@ -559,6 +559,7 @@ void XEmitter::ABI_PushAllCalleeSavedRegsAndAdjustStack() { PUSH(R14); PUSH(R15); PUSH(R15); //just to align stack. duped push/pop doesn't hurt. + // TODO: XMM? } void XEmitter::ABI_PopAllCalleeSavedRegsAndAdjustStack() { diff --git a/Common/Thunk.h b/Common/Thunk.h index f841897bd6..7ee758b5fc 100644 --- a/Common/Thunk.h +++ b/Common/Thunk.h @@ -57,6 +57,14 @@ public: Shutdown(); } void *ProtectFunction(void *function, int num_params); + + const u8 *GetSaveRegsFunction() const { + return save_regs; + } + const u8 *GetLoadRegsFunction() const { + return load_regs; + } + private: void Init(); void Shutdown(); diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index 11080096ae..7f05b3d504 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -418,13 +418,13 @@ void Jit::WriteExitDestInEAX() SetJumpTarget(tooLow); SetJumpTarget(tooHigh); - ABI_CallFunctionA(thunks.ProtectFunction((void *) Memory::GetPointer, 1), R(EAX)); + CallProtectedFunction((void *) Memory::GetPointer, R(EAX)); CMP(32, R(EAX), Imm32(0)); FixupBranch skip = J_CC(CC_NE); // TODO: "Ignore" this so other threads can continue? if (g_Config.bIgnoreBadMemAccess) - ABI_CallFunctionA(thunks.ProtectFunction((void *) Core_UpdateState, 1), Imm32(CORE_ERROR)); + CallProtectedFunction((void *) Core_UpdateState, Imm32(CORE_ERROR)); SUB(32, M(¤tMIPS->downcount), Imm32(0)); JMP(asm_.dispatcherCheckCoreState, true); @@ -607,7 +607,6 @@ OpArg Jit::JitSafeMem::PrepareMemoryOpArg(ReadType type) jit_->SUB(32, R(xaddr_), Imm32(offset_)); } - #ifdef _M_IX86 return MDisp(xaddr_, (u32) Memory::base + offset_); #else @@ -657,7 +656,7 @@ void Jit::JitSafeMem::DoSlowWrite(void *safeFunc, const OpArg src, int suboffset jit_->AND(32, R(EAX), Imm32(alignMask_)); } - jit_->ABI_CallFunctionAA(jit_->thunks.ProtectFunction(safeFunc, 2), src, R(EAX)); + jit_->CallProtectedFunction(safeFunc, src, R(EAX)); needsCheck_ = true; } @@ -680,7 +679,7 @@ bool Jit::JitSafeMem::PrepareSlowRead(void *safeFunc) jit_->AND(32, R(EAX), Imm32(alignMask_)); } - jit_->ABI_CallFunctionA(jit_->thunks.ProtectFunction(safeFunc, 1), R(EAX)); + jit_->CallProtectedFunction(safeFunc, R(EAX)); needsCheck_ = true; return true; } @@ -710,7 +709,7 @@ void Jit::JitSafeMem::NextSlowRead(void *safeFunc, int suboffset) jit_->AND(32, R(EAX), Imm32(alignMask_)); } - jit_->ABI_CallFunctionA(jit_->thunks.ProtectFunction(safeFunc, 1), R(EAX)); + jit_->CallProtectedFunction(safeFunc, R(EAX)); } bool Jit::JitSafeMem::ImmValid() @@ -755,7 +754,7 @@ void Jit::JitSafeMem::MemCheckImm(ReadType type) return; jit_->MOV(32, M(&jit_->mips_->pc), Imm32(jit_->js.compilerPC)); - jit_->ABI_CallFunctionCCC(jit_->thunks.ProtectFunction((void *)&JitMemCheck, 3), iaddr_, size_, type == MEM_WRITE ? 1 : 0); + jit_->CallProtectedFunction((void *)&JitMemCheck, iaddr_, size_, type == MEM_WRITE ? 1 : 0); jit_->CMP(32, M((void*)&coreState), Imm32(0)); skipChecks_.push_back(jit_->J_CC(CC_NE, true)); @@ -795,7 +794,7 @@ void Jit::JitSafeMem::MemCheckAsm(ReadType type) jit_->PUSH(xaddr_); jit_->MOV(32, M(&jit_->mips_->pc), Imm32(jit_->js.compilerPC)); jit_->ADD(32, R(xaddr_), Imm32(offset_)); - jit_->ABI_CallFunctionACC(jit_->thunks.ProtectFunction((void *)&JitMemCheck, 3), R(xaddr_), size_, type == MEM_WRITE ? 1 : 0); + jit_->CallProtectedFunction((void *)&JitMemCheck, R(xaddr_), size_, type == MEM_WRITE ? 1 : 0); for (int i = 0; i < 4; ++i) jit_->POP(xaddr_); @@ -812,6 +811,34 @@ void Jit::JitSafeMem::MemCheckAsm(ReadType type) } } +void Jit::CallProtectedFunction(void *func, const OpArg &arg1) +{ + // We don't regcache RCX, so the below is safe (and also faster, maybe branch prediction?) + ABI_CallFunctionA(thunks.ProtectFunction(func, 1), arg1); +} + +void Jit::CallProtectedFunction(void *func, const OpArg &arg1, const OpArg &arg2) +{ + // We don't regcache RCX/RDX, so the below is safe (and also faster, maybe branch prediction?) + ABI_CallFunctionAA(thunks.ProtectFunction(func, 2), arg1, arg2); +} + +void Jit::CallProtectedFunction(void *func, const u32 arg1, const u32 arg2, const u32 arg3) +{ + // On x64, we need to save R8, which is caller saved. + ABI_CallFunction((void *)thunks.GetSaveRegsFunction()); + ABI_CallFunctionCCC(func, arg1, arg2, arg3); + ABI_CallFunction((void *)thunks.GetLoadRegsFunction()); +} + +void Jit::CallProtectedFunction(void *func, const OpArg &arg1, const u32 arg2, const u32 arg3) +{ + // On x64, we need to save R8, which is caller saved. + ABI_CallFunction((void *)thunks.GetSaveRegsFunction()); + ABI_CallFunctionACC(func, arg1, arg2, arg3); + ABI_CallFunction((void *)thunks.GetLoadRegsFunction()); +} + void Jit::Comp_DoNothing(u32 op) { } } // namespace diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index b3f2054217..3434dee7a2 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -280,6 +280,11 @@ private: void CompFPTriArith(u32 op, void (XEmitter::*arith)(X64Reg reg, OpArg), bool orderMatters); void CompFPComp(int lhs, int rhs, u8 compare, bool allowNaN = false); + void CallProtectedFunction(void *func, const OpArg &arg1); + void CallProtectedFunction(void *func, const OpArg &arg1, const OpArg &arg2); + void CallProtectedFunction(void *func, const u32 arg1, const u32 arg2, const u32 arg3); + void CallProtectedFunction(void *func, const OpArg &arg1, const u32 arg2, const u32 arg3); + JitBlockCache blocks; JitOptions jo; JitState js;