mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-03 13:31:18 +12:00
133 lines
3.9 KiB
C++
133 lines
3.9 KiB
C++
#include "IMLInstruction.h"
|
|
#include "IMLSegment.h"
|
|
|
|
void IMLSegment::SetEnterable(uint32 enterAddress)
|
|
{
|
|
cemu_assert_debug(!isEnterable || enterPPCAddress == enterAddress);
|
|
isEnterable = true;
|
|
enterPPCAddress = enterAddress;
|
|
}
|
|
|
|
bool IMLSegment::HasSuffixInstruction() const
|
|
{
|
|
if (imlList.empty())
|
|
return false;
|
|
const IMLInstruction& imlInstruction = imlList.back();
|
|
return imlInstruction.IsSuffixInstruction();
|
|
}
|
|
|
|
sint32 IMLSegment::GetSuffixInstructionIndex() const
|
|
{
|
|
cemu_assert_debug(HasSuffixInstruction());
|
|
return (sint32)(imlList.size() - 1);
|
|
}
|
|
|
|
IMLInstruction* IMLSegment::GetLastInstruction()
|
|
{
|
|
if (imlList.empty())
|
|
return nullptr;
|
|
return &imlList.back();
|
|
}
|
|
|
|
void IMLSegment::SetLinkBranchNotTaken(IMLSegment* imlSegmentDst)
|
|
{
|
|
if (nextSegmentBranchNotTaken)
|
|
nextSegmentBranchNotTaken->list_prevSegments.erase(std::find(nextSegmentBranchNotTaken->list_prevSegments.begin(), nextSegmentBranchNotTaken->list_prevSegments.end(), this));
|
|
nextSegmentBranchNotTaken = imlSegmentDst;
|
|
if(imlSegmentDst)
|
|
imlSegmentDst->list_prevSegments.push_back(this);
|
|
}
|
|
|
|
void IMLSegment::SetLinkBranchTaken(IMLSegment* imlSegmentDst)
|
|
{
|
|
if (nextSegmentBranchTaken)
|
|
nextSegmentBranchTaken->list_prevSegments.erase(std::find(nextSegmentBranchTaken->list_prevSegments.begin(), nextSegmentBranchTaken->list_prevSegments.end(), this));
|
|
nextSegmentBranchTaken = imlSegmentDst;
|
|
if (imlSegmentDst)
|
|
imlSegmentDst->list_prevSegments.push_back(this);
|
|
}
|
|
|
|
IMLInstruction* IMLSegment::AppendInstruction()
|
|
{
|
|
IMLInstruction& inst = imlList.emplace_back();
|
|
memset(&inst, 0, sizeof(IMLInstruction));
|
|
return &inst;
|
|
}
|
|
|
|
void IMLSegment_SetLinkBranchNotTaken(IMLSegment* imlSegmentSrc, IMLSegment* imlSegmentDst)
|
|
{
|
|
// make sure segments aren't already linked
|
|
if (imlSegmentSrc->nextSegmentBranchNotTaken == imlSegmentDst)
|
|
return;
|
|
// add as next segment for source
|
|
if (imlSegmentSrc->nextSegmentBranchNotTaken != nullptr)
|
|
assert_dbg();
|
|
imlSegmentSrc->nextSegmentBranchNotTaken = imlSegmentDst;
|
|
// add as previous segment for destination
|
|
imlSegmentDst->list_prevSegments.push_back(imlSegmentSrc);
|
|
}
|
|
|
|
void IMLSegment_SetLinkBranchTaken(IMLSegment* imlSegmentSrc, IMLSegment* imlSegmentDst)
|
|
{
|
|
// make sure segments aren't already linked
|
|
if (imlSegmentSrc->nextSegmentBranchTaken == imlSegmentDst)
|
|
return;
|
|
// add as next segment for source
|
|
if (imlSegmentSrc->nextSegmentBranchTaken != nullptr)
|
|
assert_dbg();
|
|
imlSegmentSrc->nextSegmentBranchTaken = imlSegmentDst;
|
|
// add as previous segment for destination
|
|
imlSegmentDst->list_prevSegments.push_back(imlSegmentSrc);
|
|
}
|
|
|
|
void IMLSegment_RemoveLink(IMLSegment* imlSegmentSrc, IMLSegment* imlSegmentDst)
|
|
{
|
|
if (imlSegmentSrc->nextSegmentBranchNotTaken == imlSegmentDst)
|
|
{
|
|
imlSegmentSrc->nextSegmentBranchNotTaken = nullptr;
|
|
}
|
|
else if (imlSegmentSrc->nextSegmentBranchTaken == imlSegmentDst)
|
|
{
|
|
imlSegmentSrc->nextSegmentBranchTaken = nullptr;
|
|
}
|
|
else
|
|
assert_dbg();
|
|
|
|
bool matchFound = false;
|
|
for (sint32 i = 0; i < imlSegmentDst->list_prevSegments.size(); i++)
|
|
{
|
|
if (imlSegmentDst->list_prevSegments[i] == imlSegmentSrc)
|
|
{
|
|
imlSegmentDst->list_prevSegments.erase(imlSegmentDst->list_prevSegments.begin() + i);
|
|
matchFound = true;
|
|
break;
|
|
}
|
|
}
|
|
if (matchFound == false)
|
|
assert_dbg();
|
|
}
|
|
|
|
/*
|
|
* Replaces all links to segment orig with linkts to segment new
|
|
*/
|
|
void IMLSegment_RelinkInputSegment(IMLSegment* imlSegmentOrig, IMLSegment* imlSegmentNew)
|
|
{
|
|
while (imlSegmentOrig->list_prevSegments.size() != 0)
|
|
{
|
|
IMLSegment* prevSegment = imlSegmentOrig->list_prevSegments[0];
|
|
if (prevSegment->nextSegmentBranchNotTaken == imlSegmentOrig)
|
|
{
|
|
IMLSegment_RemoveLink(prevSegment, imlSegmentOrig);
|
|
IMLSegment_SetLinkBranchNotTaken(prevSegment, imlSegmentNew);
|
|
}
|
|
else if (prevSegment->nextSegmentBranchTaken == imlSegmentOrig)
|
|
{
|
|
IMLSegment_RemoveLink(prevSegment, imlSegmentOrig);
|
|
IMLSegment_SetLinkBranchTaken(prevSegment, imlSegmentNew);
|
|
}
|
|
else
|
|
{
|
|
assert_dbg();
|
|
}
|
|
}
|
|
}
|