Add support for placing midasm hooks after instructions.

This commit is contained in:
Skyth 2025-01-22 19:58:00 +03:00
parent 87e350906b
commit 3280a7cf9f
3 changed files with 73 additions and 62 deletions

View File

@ -333,84 +333,88 @@ bool Recompiler::Recompile(
};
auto midAsmHook = config.midAsmHooks.find(base);
if (midAsmHook != config.midAsmHooks.end())
{
bool returnsBool = midAsmHook->second.returnOnFalse || midAsmHook->second.returnOnTrue ||
midAsmHook->second.jumpAddressOnFalse != NULL || midAsmHook->second.jumpAddressOnTrue != NULL;
print("\t");
if (returnsBool)
print("if (");
print("{}(", midAsmHook->second.name);
for (auto& reg : midAsmHook->second.registers)
auto printMidAsmHook = [&]()
{
if (out.back() != '(')
out += ", ";
bool returnsBool = midAsmHook->second.returnOnFalse || midAsmHook->second.returnOnTrue ||
midAsmHook->second.jumpAddressOnFalse != NULL || midAsmHook->second.jumpAddressOnTrue != NULL;
switch (reg[0])
print("\t");
if (returnsBool)
print("if (");
print("{}(", midAsmHook->second.name);
for (auto& reg : midAsmHook->second.registers)
{
case 'c':
if (reg == "ctr")
out += ctr();
else
out += cr(std::atoi(reg.c_str() + 2));
break;
if (out.back() != '(')
out += ", ";
case 'x':
out += xer();
break;
switch (reg[0])
{
case 'c':
if (reg == "ctr")
out += ctr();
else
out += cr(std::atoi(reg.c_str() + 2));
break;
case 'r':
if (reg == "reserved")
out += reserved();
else
out += r(std::atoi(reg.c_str() + 1));
break;
case 'x':
out += xer();
break;
case 'f':
if (reg == "fpscr")
out += "ctx.fpscr";
else
out += f(std::atoi(reg.c_str() + 1));
break;
case 'r':
if (reg == "reserved")
out += reserved();
else
out += r(std::atoi(reg.c_str() + 1));
break;
case 'v':
out += v(std::atoi(reg.c_str() + 1));
break;
case 'f':
if (reg == "fpscr")
out += "ctx.fpscr";
else
out += f(std::atoi(reg.c_str() + 1));
break;
case 'v':
out += v(std::atoi(reg.c_str() + 1));
break;
}
}
}
if (returnsBool)
{
println(")) {{");
if (returnsBool)
{
println(")) {{");
if (midAsmHook->second.returnOnTrue)
println("\t\treturn;");
else if (midAsmHook->second.jumpAddressOnTrue != NULL)
println("\t\tgoto loc_{:X};", midAsmHook->second.jumpAddressOnTrue);
if (midAsmHook->second.returnOnTrue)
println("\t\treturn;");
else if (midAsmHook->second.jumpAddressOnTrue != NULL)
println("\t\tgoto loc_{:X};", midAsmHook->second.jumpAddressOnTrue);
println("\t}}");
println("\t}}");
println("\telse {{");
println("\telse {{");
if (midAsmHook->second.returnOnFalse)
println("\t\treturn;");
else if (midAsmHook->second.jumpAddressOnFalse != NULL)
println("\t\tgoto loc_{:X};", midAsmHook->second.jumpAddressOnFalse);
if (midAsmHook->second.returnOnFalse)
println("\t\treturn;");
else if (midAsmHook->second.jumpAddressOnFalse != NULL)
println("\t\tgoto loc_{:X};", midAsmHook->second.jumpAddressOnFalse);
println("\t}}");
}
else
{
println(");");
println("\t}}");
}
else
{
println(");");
if (midAsmHook->second.ret)
println("\treturn;");
else if (midAsmHook->second.jumpAddress != NULL)
println("\tgoto loc_{:X};", midAsmHook->second.jumpAddress);
}
}
if (midAsmHook->second.ret)
println("\treturn;");
else if (midAsmHook->second.jumpAddress != NULL)
println("\tgoto loc_{:X};", midAsmHook->second.jumpAddress);
}
};
if (midAsmHook != config.midAsmHooks.end() && !midAsmHook->second.afterInstruction)
printMidAsmHook();
int id = insn.opcode->id;
@ -2148,6 +2152,9 @@ bool Recompiler::Recompile(
fmt::println("{} at {:X} has RC bit enabled but no comparison was generated", insn.opcode->name, base);
}
#endif
if (midAsmHook != config.midAsmHooks.end() && midAsmHook->second.afterInstruction)
printMidAsmHook();
return true;
}

View File

@ -118,6 +118,8 @@ void RecompilerConfig::Load(const std::string_view& configFilePath)
fmt::println("{}: can't mix direct and conditional return/jump", midAsmHook.name);
}
midAsmHook.afterInstruction = table["after_instruction"].value_or(false);
midAsmHooks.emplace(*table["address"].value<uint32_t>(), std::move(midAsmHook));
}
}

View File

@ -18,6 +18,8 @@ struct RecompilerMidAsmHook
uint32_t jumpAddress = 0;
uint32_t jumpAddressOnTrue = 0;
uint32_t jumpAddressOnFalse = 0;
bool afterInstruction = false;
};
struct RecompilerConfig