PPCRec: Clean up code and optimize

This commit is contained in:
Exzap 2024-10-19 07:28:05 +02:00
parent 97ef9524b0
commit aa904b6d1c
5 changed files with 20 additions and 285 deletions

View File

@ -543,23 +543,31 @@ boost::container::small_vector<raLivenessRange*, 8> IMLRA_GetRangeWithFixedRegRe
void IMLRA_HandleFixedRegisters(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment)
{
// first pass - iterate over all ranges with fixed register requirements and split them if they cross the segment border (we can later optimize this)
for(raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges; currentRange; currentRange = currentRange->link_allSegmentRanges.next)
// first pass - iterate over all ranges with fixed register requirements and split them if they cross the segment border
// todo - this can be optimized. Ranges only need to be split if there are conflicts with other segments. Note that below passes rely on the fact that this pass currently splits all ranges with fixed register requirements
for(raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges; currentRange;)
{
IMLPhysRegisterSet allowedRegs;
if(!currentRange->GetAllowedRegistersEx(allowedRegs))
{
currentRange = currentRange->link_allSegmentRanges.next;
continue;
}
if(currentRange->interval2.ExtendsPreviousSegment() || currentRange->interval2.ExtendsIntoNextSegment())
{
raLivenessRange* nextRange = currentRange->link_allSegmentRanges.next;
PPCRecRA_explodeRange(ppcImlGenContext, currentRange);
// currentRange may be invalidated, therefore iterate from the beginning again (todo - can be optimized)
currentRange = imlSegment->raInfo.linkedList_allSubranges;
currentRange = nextRange;
continue;
}
currentRange = currentRange->link_allSegmentRanges.next;
}
// second pass - look for ranges with conflicting fixed register requirements and split these too (locally)
for(raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges; currentRange; currentRange = currentRange->link_allSegmentRanges.next)
{
IMLPhysRegisterSet allowedRegs;
if(currentRange->list_fixedRegRequirements.empty())
continue; // we dont need to check whole clusters because the pass above guarantees that there are no ranges with fixed register requirements that extend outside of this segment
if(!currentRange->GetAllowedRegistersEx(allowedRegs))
continue;
if(allowedRegs.HasAnyAvailable())
@ -607,6 +615,8 @@ void IMLRA_HandleFixedRegisters(ppcImlGenContext_t* ppcImlGenContext, IMLSegment
for(raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges; currentRange; currentRange = currentRange->link_allSegmentRanges.next)
{
IMLPhysRegisterSet allowedRegs;
if(currentRange->list_fixedRegRequirements.empty())
continue; // we dont need to check whole clusters because the pass above guarantees that there are no ranges with fixed register requirements that extend outside of this segment
if(!currentRange->GetAllowedRegistersEx(allowedRegs))
{
cemu_assert_debug(currentRange->list_fixedRegRequirements.empty());
@ -1074,23 +1084,8 @@ void IMLRA_FilterReservedFixedRegisterRequirementsForCluster(IMLRegisterAllocato
IMLRA_FilterReservedFixedRegisterRequirementsForSegment(ctx, currentRange, candidatePhysRegSet);
}
void __DebugTestA(IMLSegment* imlSegment)
{
// iterate all ranges
raLivenessRange* subrangeItr = imlSegment->raInfo.linkedList_allSubranges;
while(subrangeItr)
{
if(!subrangeItr->list_fixedRegRequirements.empty())
{
cemu_assert_debug(subrangeItr->HasPhysicalRegister());
}
subrangeItr = subrangeItr->link_allSegmentRanges.next;
}
}
bool IMLRA_AssignSegmentRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment)
{
DbgVerifyAllRanges(ctx);
// sort subranges ascending by start index
_sortSegmentAllSubrangesLinkedList(imlSegment);
@ -1108,7 +1103,6 @@ bool IMLRA_AssignSegmentRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenCon
RASpillStrategy_ExplodeRangeInter explodeRangeInter;
}strategy;
sint32 dbgIndex = 0;
while(subrangeItr)
{
raInstructionEdge currentRangeStart = subrangeItr->interval2.start; // used to be currentIndex before refactor
@ -1147,7 +1141,6 @@ bool IMLRA_AssignSegmentRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenCon
cemu_assert_debug(allowedRegs.HasAnyAvailable()); // if zero regs are available, then this range needs to be split to avoid mismatching register requirements (do this in the initial pass to keep the code here simpler)
candidatePhysRegSet &= allowedRegs;
__DebugTestA(imlSegment);
for (auto& liverangeItr : livenessTimeline.activeRanges)
{
cemu_assert_debug(liverangeItr->GetPhysicalRegister() >= 0);
@ -1175,7 +1168,6 @@ bool IMLRA_AssignSegmentRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenCon
subrangeItr = subrangeItr->link_allSegmentRanges.next; // next
continue;
}
__DebugTestA(imlSegment);
// there is no free register for the entire range
// evaluate different strategies of splitting ranges to free up another register or shorten the current range
strategy.localRangeHoleCutting.Reset();
@ -1205,20 +1197,17 @@ bool IMLRA_AssignSegmentRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenCon
// evaluate strategy: Explode inter-segment ranges
strategy.explodeRange.Evaluate(imlSegment, subrangeItr, livenessTimeline, allowedRegs);
SelectStrategyIfBetter(strategy.explodeRange);
__DebugTestA(imlSegment);
}
else // if subrangeItr->interval2.ExtendsIntoNextSegment()
{
strategy.explodeRangeInter.Reset();
strategy.explodeRangeInter.Evaluate(imlSegment, subrangeItr, livenessTimeline, allowedRegs);
SelectStrategyIfBetter(strategy.explodeRangeInter);
__DebugTestA(imlSegment);
}
// choose strategy
if(selectedStrategy)
{
selectedStrategy->Apply(ppcImlGenContext, imlSegment, subrangeItr);
__DebugTestA(imlSegment);
}
else
{
@ -1226,12 +1215,7 @@ bool IMLRA_AssignSegmentRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenCon
cemu_assert_debug(subrangeItr->interval2.ExtendsPreviousSegment());
// alternative strategy if we have no other choice: explode current range
PPCRecRA_explodeRange(ppcImlGenContext, subrangeItr);
__DebugTestA(imlSegment);
}
// DEBUG BEGIN
DbgVerifyAllRanges(ctx);
dbgIndex++;
// DEBUG END
return false;
}
return true;
@ -2131,37 +2115,15 @@ void IMLRegisterAllocator_AllocateRegisters(ppcImlGenContext_t* ppcImlGenContext
ctx.raParam = &raParam;
ctx.deprGenContext = ppcImlGenContext;
DbgVerifyAllRanges(ctx); // DEBUG
IMLRA_ReshapeForRegisterAllocation(ppcImlGenContext);
DbgVerifyAllRanges(ctx); // DEBUG
ppcImlGenContext->UpdateSegmentIndices(); // update momentaryIndex of each segment
DbgVerifyAllRanges(ctx); // DEBUG
ctx.perSegmentAbstractRanges.resize(ppcImlGenContext->segmentList2.size());
IMLRA_CalculateLivenessRanges(ctx);
DbgVerifyAllRanges(ctx); // DEBUG
IMLRA_ProcessFlowAndCalculateLivenessRanges(ctx);
DbgVerifyAllRanges(ctx); // DEBUG
IMLRA_AssignRegisters(ctx, ppcImlGenContext);
DbgVerifyAllRanges(ctx); // DEBUG
// debug print
//IMLDebug_Dump(ppcImlGenContext, true);
// debug print
// if (ppcImlGenContext->debug_entryPPCAddress == 0x2BDA9F4)
// {
// IMLDebug_Dump(ppcImlGenContext, true);
// __debugbreak();
// }
IMLRA_AnalyzeRangeDataFlow(ppcImlGenContext);
IMLRA_GenerateMoveInstructions(ctx);
PPCRecRA_deleteAllRanges(ppcImlGenContext);
IMLRA_DeleteAllRanges(ppcImlGenContext);
}

View File

@ -32,10 +32,10 @@ void raLivenessRange::SetPhysicalRegisterForCluster(sint32 physicalRegister)
range->physicalRegister = physicalRegister;
}
boost::container::small_vector<raLivenessRange*, 32> raLivenessRange::GetAllSubrangesInCluster()
boost::container::small_vector<raLivenessRange*, 128> raLivenessRange::GetAllSubrangesInCluster()
{
uint32 iterationIndex = PPCRecRA_getNextIterationIndex();
boost::container::small_vector<raLivenessRange*, 32> subranges;
boost::container::small_vector<raLivenessRange*, 128> subranges;
subranges.push_back(this);
this->lastIterationIndex = iterationIndex;
size_t i = 0;
@ -302,7 +302,7 @@ void PPCRecRA_deleteSubrangeCluster(ppcImlGenContext_t* ppcImlGenContext, raLive
}
}
void PPCRecRA_deleteAllRanges(ppcImlGenContext_t* ppcImlGenContext)
void IMLRA_DeleteAllRanges(ppcImlGenContext_t* ppcImlGenContext)
{
for(auto& seg : ppcImlGenContext->segmentList2)
{

View File

@ -324,7 +324,7 @@ struct raLivenessRange
// register allocator result
sint32 physicalRegister;
boost::container::small_vector<raLivenessRange*, 32> GetAllSubrangesInCluster();
boost::container::small_vector<raLivenessRange*, 128> GetAllSubrangesInCluster();
bool GetAllowedRegistersEx(IMLPhysRegisterSet& allowedRegisters); // if the cluster has fixed register requirements in any instruction this returns the combined register mask. Otherwise returns false in which case allowedRegisters is left undefined
IMLPhysRegisterSet GetAllowedRegisters(IMLPhysRegisterSet regPool); // return regPool with fixed register requirements filtered out
@ -339,7 +339,7 @@ struct raLivenessRange
raLivenessRange* PPCRecRA_createSubrange2(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, IMLRegID virtualRegister, IMLName name, raInstructionEdge startPosition, raInstructionEdge endPosition);
void PPCRecRA_deleteSubrange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange);
void PPCRecRA_deleteAllRanges(ppcImlGenContext_t* ppcImlGenContext);
void IMLRA_DeleteAllRanges(ppcImlGenContext_t* ppcImlGenContext);
void PPCRecRA_explodeRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* originRange);

View File

@ -212,85 +212,6 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP
return nullptr;
}
}
// DEBUG BEGIN
// if(ppcRecFunc->ppcAddress != 0x2BDA9F4) // TP
// {
// delete ppcRecFunc;
// return nullptr;
// }
// if(ppcRecFunc->ppcAddress < 0x2BDA9F4) // TP
// {
// delete ppcRecFunc;
// return nullptr;
// }
// this prevents the crashing
// if((ppcRecFunc->ppcAddress >= 0x02ade400 && ppcRecFunc->ppcAddress < 0x02ade600)) -> no crash
//if((ppcRecFunc->ppcAddress >= 0x02ade500 && ppcRecFunc->ppcAddress < 0x02ade600)) -> no crash
// if((ppcRecFunc->ppcAddress >= 0x02ade580 && ppcRecFunc->ppcAddress < 0x02ade600)) // -> crashed around 0x0x2b874b0 (but rare? Out of 5 runs it only crashed once)
// {
// delete ppcRecFunc;
// return nullptr;
// }
// the problem with Shovel Knight is that the crash seems to be pretty instable, at least when trying to narrow it down. Lets look for another game for now
// check TP bug...
// if(ppcRecFunc->ppcAddress >= 0x03000000) -> has bug
// if(ppcRecFunc->ppcAddress >= 0x02800000) -> no bug
// if(ppcRecFunc->ppcAddress >= 0x02C00000) -> has bug
// if(ppcRecFunc->ppcAddress >= 0x02A00000) -> no bug
// if(ppcRecFunc->ppcAddress >= 0x02B00000) -> no bug
// if(ppcRecFunc->ppcAddress >= 0x02B80000) -> has bug
// if(ppcRecFunc->ppcAddress >= 0x02B40000) -> no bug
// if(ppcRecFunc->ppcAddress >= 0x02B60000) -> no bug
// if(ppcRecFunc->ppcAddress >= 0x02B70000) -> has bug
// if(ppcRecFunc->ppcAddress >= 0x02B68000) -> no bug
// if(ppcRecFunc->ppcAddress >= 0x02B64000) -> no bug (I went into wrong direction)
// if(ppcRecFunc->ppcAddress >= 0x02B6C000) -> has bug
// if(ppcRecFunc->ppcAddress >= 0x02B6A000) -> has bug (double checked, it has bug)
// if(ppcRecFunc->ppcAddress >= 0x02B6B000) -> has bug (I went into the wrong direction again? Or does A000 have no bug??
// if(ppcRecFunc->ppcAddress >= 0x02B69000) -> has bug
// if(ppcRecFunc->ppcAddress >= 0x02B68800) -> has bug
// if(ppcRecFunc->ppcAddress >= 0x02B68400) -> no bug
// if(ppcRecFunc->ppcAddress >= 0x02B68600) -> has bug
// if(ppcRecFunc->ppcAddress >= 0x02B68500) -> no bug
// if(ppcRecFunc->ppcAddress >= 0x02B68580) -> no bug
// if(ppcRecFunc->ppcAddress >= 0x02B685C0) -> has bug
// if(ppcRecFunc->ppcAddress >= 0x02B685A0) -> has bug
// if(ppcRecFunc->ppcAddress >= 0x02B68590) -> no bug
// if(ppcRecFunc->ppcAddress >= 0x02B68598) -> has bug
// if(ppcRecFunc->ppcAddress != 0x02B68594) -> seems fine. No bug (against the expectation)
// if(ppcRecFunc->ppcAddress == 0x02B68594) -> Still has the bug
// if(ppcRecFunc->ppcAddress == 0x02B68594)
// {
// delete ppcRecFunc;
// return nullptr;
// }
// if(ppcRecFunc->ppcAddress >= 0x2B7A8D4 && ppcRecFunc->ppcAddress < 0x02B7AC9C && ppcRecFunc->ppcAddress != 0x2B7A8D4)
// {
// delete ppcRecFunc;
// return nullptr;
// }
// doing both of these means no bug!
// excluding just ppcAddress == 0x2B7A8D4 is enough to trigger the bug again. So it definitely that function
// next: Debug it!
// In Pikmin 3 030a9998 is broken?
// if(!(ppcRecFunc->ppcAddress >= 0x030a9998 && ppcRecFunc->ppcAddress < 0x030AA208))
// {
// delete ppcRecFunc;
// return nullptr;
// }
// else
// {
// delete ppcRecFunc;
// return nullptr;
// }
// DEBUG END
// apply passes
if (!PPCRecompiler_ApplyIMLPasses(ppcImlGenContext))
@ -299,90 +220,11 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP
return nullptr;
}
// TP
// if (ppcRecFunc->ppcAddress == 0x2B7A8D4)
// {
// debug_printf("----------------------------------------\n");
// IMLDebug_Dump(&ppcImlGenContext);
// //__debugbreak();
// }
// // Bad Function in SM3DW
// if (ppcRecFunc->ppcAddress == 0x023D5768)
// {
// debug_printf("----------------------------------------\n");
// IMLDebug_Dump(&ppcImlGenContext);
// }
// if (ppcRecFunc->ppcAddress >= 0x023D5768 && ppcRecFunc->ppcAddress < 0x023D58DC)
// {
// delete ppcRecFunc;
// return nullptr;
// }
//
//
// // 0x02846c74
// if (ppcRecFunc->ppcAddress == 0x02846c74)
// {
// debug_printf("----------------------------------------\n");
// IMLDebug_Dump(&ppcImlGenContext);
// __debugbreak();
// }
// Shovel Knight
// if (ppcRecFunc->ppcAddress >= 0x02A1E630 && ppcRecFunc->ppcAddress < 0x02A1E9D8)
// {
// // debug_printf("----------------------------------------\n");
// // IMLDebug_Dump(&ppcImlGenContext);
// // __debugbreak();
// delete ppcRecFunc;
// return nullptr;
// }
//
// //
// if (ppcRecFunc->ppcAddress == 0x02ade5c4 || ppcRecFunc->ppcAddress == 0x02ade5c8)
// {
// // debug_printf("----------------------------------------\n");
// IMLDebug_Dump(&ppcImlGenContext);
// __debugbreak();
// }
// else
// {
// delete ppcRecFunc;
// return nullptr;
// }
//if (ppcRecFunc->ppcAddress == 0x11223344)
//{
// //debug_printf("----------------------------------------\n");
// //IMLDebug_Dump(&ppcImlGenContext);
// //__debugbreak();
//}
//else
//{
// delete ppcRecFunc;
// return nullptr;
//}
// if (ppcRecFunc->ppcAddress >= 0x2BDA9F4 && ppcRecFunc->ppcAddress < 0x02BDAB38)
// {
// return nullptr;
// //IMLDebug_Dump(&ppcImlGenContext);
// //__debugbreak();
// }
// if (ppcRecFunc->ppcAddress == 0x2BDA9F4)
// {
// IMLDebug_Dump(&ppcImlGenContext);
// __debugbreak();
// }
// 31A8778
// if(ppcRecFunc->ppcAddress >= 0x2759E20 && ppcRecFunc->ppcAddress < 0x0275A0CC)
// {
// delete ppcRecFunc;
// return nullptr;
// }
// Functions for testing (botw):
// 3B4049C (large with switch case)

View File

@ -2876,75 +2876,6 @@ bool PPCIMLGen_FillBasicBlock(ppcImlGenContext_t& ppcImlGenContext, PPCBasicBloc
uint32 addressOfCurrentInstruction = (uint32)((uint8*)ppcImlGenContext.currentInstruction - memory_base);
ppcImlGenContext.ppcAddressOfCurrentInstruction = addressOfCurrentInstruction;
// DEBUG BEGIN
// if(ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7A8D4+0x10) -> stops bug
// if(ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7A9C0) -> has bug (optional code path)
// if(ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7AA50) -> stops bug
// if(ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7AC34) -> stops bug
// if(ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7AC78) -> has bug
// if(ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7AC70) -> has bug
// if(ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7AC88) -> has bug
// if(ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02B7AC3C) -> has bug
// if(ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02B7AC38) -> no bug
// weirdly, excluding 0x02B7AC38 fixes the issue. Excluding both 0x02B7AC3C and 0x2B7AC88 (the follow up instructions) does not fix the bug
// if(ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7ABE4) -> has bug
// if(ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02B7AAD0) -> fixes bug
// maybe try to place as many leave instructions as possible while keeping the bug alive
// eventually we should end up with a relatively small IR footprint that is easier to analyze
// 0x023d5818
// SM3DW debug
// if(ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x23D58A8)
// {
// ppcImlGenContext.emitInst().make_macro(PPCREC_IML_MACRO_DEBUGBREAK, ppcImlGenContext.ppcAddressOfCurrentInstruction, 0, 0, IMLREG_INVALID);
// }
#if 0 // TP
if(ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7AC78 || // verified
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7AC70 || // verified
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7A9C0 || // verified
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02B7AC3C || // verified
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02B7AADC || // verified
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02B7ABE4 || // verified
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7ABC0 || // verified
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7ABA8 || // verified
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7AB90 || // verified
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7AB04 || // verified
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02b7abc4 || // verified
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02B7A9B0 || // verified
//ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02b7aa10 -> fixes bug (this is after a bl)
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02B7AA3C || // verified
//ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7AA44 -> fixes bug (this is on the main path, the one before, 0x02B7AA3C, does not break)
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02B7AADC || // verified
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02B7ABC4 || // verified
ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02b7ac88 || // verified
// ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02b7aad0 || -> fixes it
// ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02b7aa30 || -> fixes it (mostly. There was a small glitch on eponas tail?)
//ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02b7aa24 || -> this fixes it
//ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7A918 || -> this fixes it
//ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02B7A9A0 || -> this fixes it
//ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x02B7AC38 || -> this fixes it
//ppcImlGenContext.ppcAddressOfCurrentInstruction == 0x2B7A8D4 || -> this fixes it
(ppcImlGenContext.ppcAddressOfCurrentInstruction >= 0x2B7AC44 && ppcImlGenContext.ppcAddressOfCurrentInstruction <= 0x2B7AC84) || // verified
(ppcImlGenContext.ppcAddressOfCurrentInstruction >= 0x02B7AADC && ppcImlGenContext.ppcAddressOfCurrentInstruction <= 0x2B7ABC0) || // verified
(ppcImlGenContext.ppcAddressOfCurrentInstruction >= 0x2B7A9B0 && ppcImlGenContext.ppcAddressOfCurrentInstruction <= 0x02B7AA0C) ||
(ppcImlGenContext.ppcAddressOfCurrentInstruction >= 0x02B7AAE4 && ppcImlGenContext.ppcAddressOfCurrentInstruction <= 0x02b7ac20) // verified
// disabling IMLOptimizerX86_SubstituteCJumpForEflagsJump fixes it...
//(ppcImlGenContext.ppcAddressOfCurrentInstruction >= 0x2B7AA1C && ppcImlGenContext.ppcAddressOfCurrentInstruction <= 0x02B7AA40) -> fixes it
)
{
ppcImlGenContext.emitInst().make_macro(PPCREC_IML_MACRO_LEAVE, ppcImlGenContext.ppcAddressOfCurrentInstruction, 0, 0, IMLREG_INVALID);
// this doesnt work any longer because the basic blocks are determined before the recompiler is called
basicBlockInfo.GetSegmentForInstructionAppend()->SetLinkBranchTaken(nullptr);
basicBlockInfo.GetSegmentForInstructionAppend()->SetLinkBranchNotTaken(nullptr);
break; // but we should be able to just exit the block early?
}
#endif
if (PPCRecompiler_decodePPCInstruction(&ppcImlGenContext))
{
debug_printf("Recompiler encountered unsupported instruction at 0x%08x\n", addressOfCurrentInstruction);