x86jit: Check CALL dist for safe memory funcs.

This commit is contained in:
Unknown W. Brackets 2022-01-21 19:19:40 -08:00
parent 212e730e98
commit 8573c34f85
4 changed files with 60 additions and 16 deletions

View File

@ -431,6 +431,11 @@ void XEmitter::CALL(const void *fnptr)
Write32(u32(distance));
}
bool XEmitter::CanCALLDirect(const void *fnptr) {
u64 distance = u64(fnptr) - (u64(code) + 5);
return distance < 0x0000000080000000ULL || distance >= 0xFFFFFFFF80000000ULL;
}
FixupBranch XEmitter::J(bool force5bytes)
{
FixupBranch branch;

View File

@ -444,6 +444,7 @@ public:
#ifdef CALL
#undef CALL
#endif
bool CanCALLDirect(const void *fnptr);
void CALL(const void *fnptr);
void CALLptr(OpArg arg);

View File

@ -242,8 +242,9 @@ bool JitSafeMem::PrepareSlowWrite()
return false;
}
void JitSafeMem::DoSlowWrite(const void *safeFunc, const OpArg& src, int suboffset)
{
void JitSafeMem::DoSlowWrite(const void *safeFunc, const OpArg &src, int suboffset) {
_dbg_assert_msg_(safeFunc != nullptr, "Safe func cannot be null");
if (iaddr_ != (u32) -1)
jit_->MOV(32, R(EAX), Imm32((iaddr_ + suboffset) & alignMask_));
else
@ -263,26 +264,27 @@ void JitSafeMem::DoSlowWrite(const void *safeFunc, const OpArg& src, int suboffs
jit_->MOV(32, MIPSSTATE_VAR(pc), Imm32(jit_->GetCompilerPC()));
}
// This is a special jit-ABI'd function.
jit_->CALL(safeFunc);
if (jit_->CanCALLDirect(safeFunc)) {
jit_->CALL(safeFunc);
} else {
// We can't safely flush a reg, but this shouldn't be normal.
IndirectCALL(safeFunc);
}
#if PPSSPP_ARCH(32BIT)
jit_->POP(EDX);
#endif
needsCheck_ = true;
}
bool JitSafeMem::PrepareSlowRead(const void *safeFunc)
{
if (!fast_)
{
if (iaddr_ != (u32) -1)
{
bool JitSafeMem::PrepareSlowRead(const void *safeFunc) {
_dbg_assert_msg_(safeFunc != nullptr, "Safe func cannot be null");
if (!fast_) {
if (iaddr_ != (u32) -1) {
// No slow read necessary.
if (ImmValid())
return false;
jit_->MOV(32, R(EAX), Imm32(iaddr_ & alignMask_));
}
else
{
} else {
PrepareSlowAccess();
jit_->LEA(32, EAX, MDisp(xaddr_, offset_));
if (alignMask_ != 0xFFFFFFFF)
@ -293,7 +295,12 @@ bool JitSafeMem::PrepareSlowRead(const void *safeFunc)
jit_->MOV(32, MIPSSTATE_VAR(pc), Imm32(jit_->GetCompilerPC()));
}
// This is a special jit-ABI'd function.
jit_->CALL(safeFunc);
if (jit_->CanCALLDirect(safeFunc)) {
jit_->CALL(safeFunc);
} else {
// We can't safely flush a reg, but this shouldn't be normal.
IndirectCALL(safeFunc);
}
needsCheck_ = true;
return true;
}
@ -301,8 +308,8 @@ bool JitSafeMem::PrepareSlowRead(const void *safeFunc)
return false;
}
void JitSafeMem::NextSlowRead(const void *safeFunc, int suboffset)
{
void JitSafeMem::NextSlowRead(const void *safeFunc, int suboffset) {
_dbg_assert_msg_(safeFunc != nullptr, "Safe func cannot be null");
_dbg_assert_msg_(!fast_, "NextSlowRead() called in fast memory mode?");
// For simplicity, do nothing for 0. We already read in PrepareSlowRead().
@ -327,7 +334,12 @@ void JitSafeMem::NextSlowRead(const void *safeFunc, int suboffset)
jit_->MOV(32, MIPSSTATE_VAR(pc), Imm32(jit_->GetCompilerPC()));
}
// This is a special jit-ABI'd function.
jit_->CALL(safeFunc);
if (jit_->CanCALLDirect(safeFunc)) {
jit_->CALL(safeFunc);
} else {
// We can't safely flush a reg, but this shouldn't be normal.
IndirectCALL(safeFunc);
}
}
bool JitSafeMem::ImmValid()
@ -335,6 +347,24 @@ bool JitSafeMem::ImmValid()
return iaddr_ != (u32) -1 && Memory::IsValidAddress(iaddr_) && Memory::IsValidAddress(iaddr_ + size_ - 1);
}
void JitSafeMem::IndirectCALL(const void *safeFunc) {
#if PPSSPP_ARCH(32BIT)
jit_->PUSH(ECX);
jit_->SUB(PTRBITS, R(ESP), Imm8(16 - 4));
jit_->MOV(PTRBITS, R(ECX), ImmPtr(safeFunc));
jit_->CALLptr(R(RCX));
jit_->ADD(PTRBITS, R(ESP), Imm8(16 - 4));
jit_->POP(ECX);
#else
jit_->PUSH(RCX);
jit_->SUB(PTRBITS, R(RSP), Imm8(8));
jit_->MOV(PTRBITS, R(RCX), ImmPtr(safeFunc));
jit_->CALLptr(R(RCX));
jit_->ADD(64, R(RSP), Imm8(8));
jit_->POP(RCX);
#endif
}
void JitSafeMem::Finish()
{
// Memory::Read_U32/etc. may have tripped coreState.
@ -451,6 +481,13 @@ void JitSafeMemFuncs::Init(ThunkManager *thunks) {
void JitSafeMemFuncs::Shutdown() {
ResetCodePtr(0);
FreeCodeSpace();
readU32 = nullptr;
readU16 = nullptr;
readU8 = nullptr;
writeU32 = nullptr;
writeU16 = nullptr;
writeU8 = nullptr;
}
// Mini ABI:

View File

@ -72,6 +72,7 @@ private:
void MemCheckImm(MemoryOpType type);
void MemCheckAsm(MemoryOpType type);
bool ImmValid();
void IndirectCALL(const void *safeFunc);
Jit *jit_;
MIPSGPReg raddr_;