This commit is contained in:
ApfelTeeSaft 2025-11-05 08:52:03 +01:00 committed by GitHub
commit ec2a213e1a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 49 additions and 22 deletions

View file

@ -254,15 +254,16 @@ void Recompiler::Analyse()
std::sort(functions.begin(), functions.end(), [](auto& lhs, auto& rhs) { return lhs.base < rhs.base; });
}
bool Recompiler::Recompile(
const Function& fn,
uint32_t base,
const ppc_insn& insn,
const uint32_t* data,
std::unordered_map<uint32_t, RecompilerSwitchTable>::iterator& switchTable,
RecompilerLocalVariables& localVariables,
CSRState& csrState)
bool Recompiler::Recompile(const RecompileArgs& args)
{
const Function& fn = args.fn;
uint32_t base = args.base;
const ppc_insn& insn = args.insn;
const uint32_t* data = args.data;
auto& switchTable = args.switchTable;
RecompilerLocalVariables& localVariables = args.localVariables;
CSRState& csrState = args.csrState;
println("\t// {} {}", insn.opcode->name, insn.op_str);
// TODO: we could cache these formats in an array
@ -363,9 +364,11 @@ bool Recompiler::Recompile(
return "ea";
};
// TODO (Sajid): Check for out of bounds access
auto mmioStore = [&]() -> bool
{
// Check if the next instruction is within bounds
if (base + 4 >= fn.base + fn.size)
return false;
return *(data + 1) == c_eieio;
};
@ -1255,8 +1258,21 @@ bool Recompiler::Recompile(
break;
case PPC_INST_MFOCRF:
// TODO: don't hardcode to cr6
println("\t{}.u64 = ({}.lt << 7) | ({}.gt << 6) | ({}.eq << 5) | ({}.so << 4);", r(insn.operands[0]), cr(6), cr(6), cr(6), cr(6));
{
// Decode FXM field mask to determine which CR field to read
// FXM is an 8-bit mask where bit 0 (0x80) = cr0, bit 1 (0x40) = cr1, etc.
uint32_t fxm = insn.operands[1];
size_t crField = 0;
for (size_t i = 0; i < 8; i++)
{
if (fxm & (0x80 >> i))
{
crField = i;
break;
}
}
println("\t{}.u64 = ({}.lt << 7) | ({}.gt << 6) | ({}.eq << 5) | ({}.so << 4);", r(insn.operands[0]), cr(crField), cr(crField), cr(crField), cr(crField));
}
break;
case PPC_INST_MFTB:
@ -2427,7 +2443,7 @@ bool Recompiler::Recompile(const Function& fn)
if (insn.opcode->id == PPC_INST_BCTR && (*(data - 1) == 0x07008038 || *(data - 1) == 0x00000060) && switchTable == config.switchTables.end())
fmt::println("Found a switch jump table at {:X} with no switch table entry present", base);
if (!Recompile(fn, base, insn, data, switchTable, localVariables, csrState))
if (!Recompile(RecompileArgs{fn, base, insn, data, switchTable, localVariables, csrState}))
{
fmt::println("Unrecognized instruction at 0x{:X}: {}", base, insn.opcode->name);
allRecompiled = false;

View file

@ -25,6 +25,17 @@ enum class CSRState
VMX
};
struct RecompileArgs
{
const Function& fn;
uint32_t base;
const ppc_insn& insn;
const uint32_t* data;
std::unordered_map<uint32_t, RecompilerSwitchTable>::iterator& switchTable;
RecompilerLocalVariables& localVariables;
CSRState& csrState;
};
struct Recompiler
{
// Enforce In-order Execution of I/O constant for quick comparison
@ -52,15 +63,7 @@ struct Recompiler
void Analyse();
// TODO: make a RecompileArgs struct instead this is getting messy
bool Recompile(
const Function& fn,
uint32_t base,
const ppc_insn& insn,
const uint32_t* data,
std::unordered_map<uint32_t, RecompilerSwitchTable>::iterator& switchTable,
RecompilerLocalVariables& localVariables,
CSRState& csrState);
bool Recompile(const RecompileArgs& args);
bool Recompile(const Function& fn);

View file

@ -213,7 +213,15 @@ void TestRecompiler::RecompileTests(const char* srcDirectoryPath, const char* ds
int secondSpaceIndex = str.find(' ', spaceIndex + 1);
auto reg = str.substr(spaceIndex + 1, secondSpaceIndex - spaceIndex - 1);
if (reg[0] == 'c')
continue; // TODO
{
// CR register: parse 4-bit value (lt, gt, eq, so)
auto value = str.substr(secondSpaceIndex + 1);
fmt::println(file, "\tPPC_CHECK_VALUE_U({}, ctx.{}.lt, ({}) >> 3 & 1);", name, reg, value);
fmt::println(file, "\tPPC_CHECK_VALUE_U({}, ctx.{}.gt, ({}) >> 2 & 1);", name, reg, value);
fmt::println(file, "\tPPC_CHECK_VALUE_U({}, ctx.{}.eq, ({}) >> 1 & 1);", name, reg, value);
fmt::println(file, "\tPPC_CHECK_VALUE_U({}, ctx.{}.so, ({}) & 1);", name, reg, value);
continue;
}
if (reg[0] == 'v')
{
int openingBracketIndex = str.find('[', secondSpaceIndex + 1);