Skip to content

Commit

Permalink
CachedInterpreter: Factor function hooking code out of Jit()
Browse files Browse the repository at this point in the history
Extracts the self-contained code into its own function to clean up the
flow of Jit() a little more.

This also introduces a helper function to HLE.h that will be used to
reduce the boilerplate here and in the interpreter and Jit64 in the
following commits.

This function performs all of the preliminary checks required prior to
attempting to hook/replace a function at a given address. The function then
calls a provided object that satisfies the FunctionObject concept in the
C++ standard library. This can be a lambda, a regular function pointer,
an object with an overloaded function call operator, etc. The only
requirement is that the function return a bool, indicating whether or
not the function was replaced, and that it can take parameters in the
form: fn(u32 function, HLE::HookType type)
  • Loading branch information
lioncash committed May 16, 2018
1 parent b547f72 commit 4b25538
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 20 deletions.
29 changes: 29 additions & 0 deletions Source/Core/Core/HLE/HLE.h
Expand Up @@ -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
37 changes: 17 additions & 20 deletions Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp
Expand Up @@ -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 ||
Expand Down Expand Up @@ -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)
{ {
Expand Down
Expand Up @@ -38,6 +38,8 @@ class CachedInterpreter : public JitBase
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;
Expand Down

0 comments on commit 4b25538

Please sign in to comment.