mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-08 21:53:31 +01:00
Merge pull request #6856 from lioncash/cached-hook
PowerPC: Factor common part of function hooking code out of the interpreter and JITs
This commit is contained in:
commit
1424964678
@ -42,4 +42,33 @@ HookType GetFunctionTypeByIndex(u32 index);
|
|||||||
HookFlag GetFunctionFlagsByIndex(u32 index);
|
HookFlag GetFunctionFlagsByIndex(u32 index);
|
||||||
|
|
||||||
bool IsEnabled(HookFlag flag);
|
bool IsEnabled(HookFlag flag);
|
||||||
|
|
||||||
|
// Performs the backend-independent preliminary checking before calling a
|
||||||
|
// FunctionObject to do the actual replacing. Typically, this callback will
|
||||||
|
// be in the backend itself, containing the backend-specific portions
|
||||||
|
// required in replacing a function.
|
||||||
|
//
|
||||||
|
// fn may be any object that satisfies the FunctionObject concept in the C++
|
||||||
|
// standard library. That is, any lambda, object with an overloaded function
|
||||||
|
// call operator, or regular function pointer.
|
||||||
|
//
|
||||||
|
// fn must return a bool indicating whether or not function replacing occurred.
|
||||||
|
// fn must also accept a parameter list of the form: fn(u32 function, HLE::HookType type).
|
||||||
|
template <typename FunctionObject>
|
||||||
|
bool ReplaceFunctionIfPossible(u32 address, FunctionObject fn)
|
||||||
|
{
|
||||||
|
const u32 function = GetFirstFunctionIndex(address);
|
||||||
|
if (function == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const HookType type = GetFunctionTypeByIndex(function);
|
||||||
|
if (type != HookType::Start && type != HookType::Replace)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const HookFlag flags = GetFunctionFlagsByIndex(function);
|
||||||
|
if (!IsEnabled(flags))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return fn(function, type);
|
||||||
}
|
}
|
||||||
|
} // namespace HLE
|
||||||
|
@ -171,6 +171,21 @@ static bool CheckDSI(u32 data)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CachedInterpreter::HandleFunctionHooking(u32 address)
|
||||||
|
{
|
||||||
|
return HLE::ReplaceFunctionIfPossible(address, [&](u32 function, HLE::HookType type) {
|
||||||
|
m_code.emplace_back(WritePC, address);
|
||||||
|
m_code.emplace_back(Interpreter::HLEFunction, function);
|
||||||
|
|
||||||
|
if (type != HLE::HookType::Replace)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_code.emplace_back(EndBlock, js.downcountAmount);
|
||||||
|
m_code.emplace_back();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void CachedInterpreter::Jit(u32 address)
|
void CachedInterpreter::Jit(u32 address)
|
||||||
{
|
{
|
||||||
if (m_code.size() >= CODE_SIZE / sizeof(Instruction) - 0x1000 ||
|
if (m_code.size() >= CODE_SIZE / sizeof(Instruction) - 0x1000 ||
|
||||||
@ -208,26 +223,8 @@ void CachedInterpreter::Jit(u32 address)
|
|||||||
|
|
||||||
js.downcountAmount += op.opinfo->numCycles;
|
js.downcountAmount += op.opinfo->numCycles;
|
||||||
|
|
||||||
u32 function = HLE::GetFirstFunctionIndex(op.address);
|
if (HandleFunctionHooking(op.address))
|
||||||
if (function != 0)
|
break;
|
||||||
{
|
|
||||||
HLE::HookType type = HLE::GetFunctionTypeByIndex(function);
|
|
||||||
if (type == HLE::HookType::Start || type == HLE::HookType::Replace)
|
|
||||||
{
|
|
||||||
HLE::HookFlag flags = HLE::GetFunctionFlagsByIndex(function);
|
|
||||||
if (HLE::IsEnabled(flags))
|
|
||||||
{
|
|
||||||
m_code.emplace_back(WritePC, op.address);
|
|
||||||
m_code.emplace_back(Interpreter::HLEFunction, function);
|
|
||||||
if (type == HLE::HookType::Replace)
|
|
||||||
{
|
|
||||||
m_code.emplace_back(EndBlock, js.downcountAmount);
|
|
||||||
m_code.emplace_back();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!op.skip)
|
if (!op.skip)
|
||||||
{
|
{
|
||||||
|
@ -38,6 +38,8 @@ private:
|
|||||||
const u8* GetCodePtr() const;
|
const u8* GetCodePtr() const;
|
||||||
void ExecuteOneBlock();
|
void ExecuteOneBlock();
|
||||||
|
|
||||||
|
bool HandleFunctionHooking(u32 address);
|
||||||
|
|
||||||
BlockCache m_block_cache{*this};
|
BlockCache m_block_cache{*this};
|
||||||
std::vector<Instruction> m_code;
|
std::vector<Instruction> m_code;
|
||||||
PPCAnalyst::CodeBuffer code_buffer;
|
PPCAnalyst::CodeBuffer code_buffer;
|
||||||
|
@ -99,32 +99,17 @@ static void Trace(UGeckoInstruction& inst)
|
|||||||
PowerPC::ppcState.spr[8], regs.c_str(), inst.hex, ppc_inst.c_str());
|
PowerPC::ppcState.spr[8], regs.c_str(), inst.hex, ppc_inst.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Interpreter::HandleFunctionHooking(u32 address)
|
||||||
|
{
|
||||||
|
return HLE::ReplaceFunctionIfPossible(address, [](u32 function, HLE::HookType type) {
|
||||||
|
HLEFunction(function);
|
||||||
|
return type != HLE::HookType::Start;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
int Interpreter::SingleStepInner()
|
int Interpreter::SingleStepInner()
|
||||||
{
|
{
|
||||||
u32 function = HLE::GetFirstFunctionIndex(PC);
|
if (!HandleFunctionHooking(PC))
|
||||||
if (function != 0)
|
|
||||||
{
|
|
||||||
HLE::HookType type = HLE::GetFunctionTypeByIndex(function);
|
|
||||||
if (type == HLE::HookType::Start || type == HLE::HookType::Replace)
|
|
||||||
{
|
|
||||||
HLE::HookFlag flags = HLE::GetFunctionFlagsByIndex(function);
|
|
||||||
if (HLE::IsEnabled(flags))
|
|
||||||
{
|
|
||||||
HLEFunction(function);
|
|
||||||
if (type == HLE::HookType::Start)
|
|
||||||
{
|
|
||||||
// Run the original.
|
|
||||||
function = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
function = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (function == 0)
|
|
||||||
{
|
{
|
||||||
#ifdef USE_GDBSTUB
|
#ifdef USE_GDBSTUB
|
||||||
if (gdb_active() && gdb_bp_x(PC))
|
if (gdb_active() && gdb_bp_x(PC))
|
||||||
|
@ -284,6 +284,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
static void InitializeInstructionTables();
|
static void InitializeInstructionTables();
|
||||||
|
|
||||||
|
static bool HandleFunctionHooking(u32 address);
|
||||||
|
|
||||||
// flag helper
|
// flag helper
|
||||||
static void Helper_UpdateCR0(u32 value);
|
static void Helper_UpdateCR0(u32 value);
|
||||||
static void Helper_UpdateCR1();
|
static void Helper_UpdateCR1();
|
||||||
|
@ -806,26 +806,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBloc
|
|||||||
SetJumpTarget(noExtIntEnable);
|
SetJumpTarget(noExtIntEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 function = HLE::GetFirstFunctionIndex(op.address);
|
if (HandleFunctionHooking(op.address))
|
||||||
if (function != 0)
|
break;
|
||||||
{
|
|
||||||
HLE::HookType type = HLE::GetFunctionTypeByIndex(function);
|
|
||||||
if (type == HLE::HookType::Start || type == HLE::HookType::Replace)
|
|
||||||
{
|
|
||||||
HLE::HookFlag flags = HLE::GetFunctionFlagsByIndex(function);
|
|
||||||
if (HLE::IsEnabled(flags))
|
|
||||||
{
|
|
||||||
HLEFunction(function);
|
|
||||||
if (type == HLE::HookType::Replace)
|
|
||||||
{
|
|
||||||
MOV(32, R(RSCRATCH), PPCSTATE(npc));
|
|
||||||
js.downcountAmount += js.st.numCycles;
|
|
||||||
WriteExitDestInRSCRATCH();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!op.skip)
|
if (!op.skip)
|
||||||
{
|
{
|
||||||
@ -1042,3 +1024,18 @@ void Jit64::IntializeSpeculativeConstants()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Jit64::HandleFunctionHooking(u32 address)
|
||||||
|
{
|
||||||
|
return HLE::ReplaceFunctionIfPossible(address, [&](u32 function, HLE::HookType type) {
|
||||||
|
HLEFunction(function);
|
||||||
|
|
||||||
|
if (type != HLE::HookType::Replace)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MOV(32, R(RSCRATCH), PPCSTATE(npc));
|
||||||
|
js.downcountAmount += js.st.numCycles;
|
||||||
|
WriteExitDestInRSCRATCH();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -234,6 +234,8 @@ private:
|
|||||||
static void InitializeInstructionTables();
|
static void InitializeInstructionTables();
|
||||||
void CompileInstruction(PPCAnalyst::CodeOp& op);
|
void CompileInstruction(PPCAnalyst::CodeOp& op);
|
||||||
|
|
||||||
|
bool HandleFunctionHooking(u32 address);
|
||||||
|
|
||||||
void AllocStack();
|
void AllocStack();
|
||||||
void FreeStack();
|
void FreeStack();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user