project64/Source/Project64/N64 System/Recompiler/Section Info.cpp

306 lines
7.8 KiB
C++
Raw Normal View History

#include "stdafx.h"
CCodeBlock::CCodeBlock(DWORD VAddrEnter, BYTE * RecompPos, bool bDelaySlot) :
m_VAddrEnter(VAddrEnter),
m_VAddrFirst(VAddrEnter),
m_VAddrLast(VAddrEnter),
m_CompiledLocation(RecompPos),
m_NoOfSections(1),
m_EnterSection(this, VAddrEnter, 1),
m_bDelaySlot(bDelaySlot)
{
AnalyseBlock();
}
bool CCodeBlock::AnalyseBlock ( void )
{
if (bLinkBlocks())
{
if (!m_EnterSection.CreateSectionLinkage ()) { return false; }
m_EnterSection.DetermineLoop(NextTest(),NextTest(), m_EnterSection.m_SectionID);
while (m_EnterSection.FixConstants(NextTest())) {}
}
return true;
}
bool CCodeBlock::Compile()
{
if (m_bDelaySlot)
{
CPU_Message("====== Delay Block ======");
} else {
CPU_Message("====== Code Block ======");
}
CPU_Message("x86 code at: %X",CompiledLocation());
CPU_Message("Start of Block: %X",VAddrEnter() );
CPU_Message("No of Sections: %d",NoOfSections() );
CPU_Message("====== recompiled code ======");
if (m_bDelaySlot)
{
Pop(x86_EAX);
MoveX86regToVariable(x86_EAX,_PROGRAM_COUNTER,"_PROGRAM_COUNTER");
} else {
EnterCodeBlock();
}
if (m_bDelaySlot)
{
m_EnterSection.GenerateX86Code(m_EnterSection.m_Test + 1);
} else {
#ifdef tofix
if (bLinkBlocks()) {
for (int count = 0; count < BlockInfo.NoOfSections; count ++) {
DisplaySectionInformation(&BlockInfo.ParentSection,count + 1,CBlockSection::GetNewTestValue());
}
}
if (m_SyncSystem) {
//if ((DWORD)BlockInfo.CompiledLocation == 0x60A7B73B) { X86BreakPoint(__FILE__,__LINE__); }
//MoveConstToVariable((DWORD)BlockInfo.CompiledLocation,&CurrentBlock,"CurrentBlock");
}
#endif
#ifdef tofix
if (bLinkBlocks()) {
while (GenerateX86Code(BlockInfo,&BlockInfo.ParentSection,CBlockSection::GetNewTestValue()));
} else {
#endif
if (!m_EnterSection.GenerateX86Code(m_EnterSection.m_Test + 1))
{
return false;
}
#ifdef tofix
}
#endif
}
CompileExitCode();
DWORD PAddr;
_TransVaddr->TranslateVaddr(VAddrFirst(),PAddr);
MD5(_MMU->Rdram() + PAddr,(VAddrLast() - VAddrFirst()) + 4).get_digest(m_Hash);
return true;
}
void CCodeBlock::CompileExitCode ( void )
{
for (EXIT_LIST::iterator ExitIter = m_ExitInfo.begin(); ExitIter != m_ExitInfo.end(); ExitIter++)
{
CPU_Message("");
CPU_Message(" $Exit_%d",ExitIter->ID);
SetJump32(ExitIter->JumpLoc,(DWORD *)m_RecompPos);
m_NextInstruction = ExitIter->NextInstruction;
m_EnterSection.CompileExit(-1, ExitIter->TargetPC,ExitIter->ExitRegSet,ExitIter->reason,true,NULL);
}
}
CJumpInfo::CJumpInfo()
{
TargetPC = (DWORD)-1;
BranchLabel = "";
LinkLocation = NULL;
LinkLocation2 = NULL;
FallThrough = false;
PermLoop = false;
DoneDelaySlot = false;
}
#ifdef tofix
bool CCodeSection::IsAllParentLoops(CCodeSection * Parent, bool IgnoreIfCompiled, DWORD Test)
{
if (IgnoreIfCompiled && Parent->CompiledLocation != NULL) { return true; }
if (!InLoop) { return false; }
if (!Parent->InLoop) { return false; }
if (Parent->ParentSection.empty()) { return false; }
if (this == Parent) { return true; }
if (Parent->Test == Test) { return true; }
Parent->Test = Test;
for (SECTION_LIST::iterator iter = Parent->ParentSection.begin(); iter != Parent->ParentSection.end(); iter++)
{
CCodeSection * ParentSection = *iter;
if (!IsAllParentLoops(ParentSection,IgnoreIfCompiled,Test)) { return false; }
}
return true;
}
void CCodeSection::UnlinkParent( CCodeSection * Parent, bool AllowDelete, bool ContinueSection )
{
if (this == NULL)
{
return;
}
SECTION_LIST::iterator iter = ParentSection.begin();
while ( iter != ParentSection.end())
{
CCodeSection * ParentIter = *iter;
if (ParentIter == Parent && (Parent->ContinueSection != this || Parent->JumpSection != this))
{
ParentSection.erase(iter);
iter = ParentSection.begin();
} else {
iter++;
}
}
// if (Parent->ContinueSection != Parent->JumpSection)
// {
// if (!ContinueSection && Parent->ContinueSection == this)
// {
// _Notify->BreakPoint(__FILE__,__LINE__);
// }
// }
if (ContinueSection && Parent->ContinueSection == this)
{
Parent->ContinueSection = NULL;
}
// if (Parent->ContinueSection != Parent->JumpSection)
// {
// if (ContinueSection && Parent->JumpSection == this)
// {
// _Notify->BreakPoint(__FILE__,__LINE__);
// }
// }
if (!ContinueSection && Parent->JumpSection == this)
{
Parent->JumpSection = NULL;
}
if (AllowDelete)
{
bool KillMe = true;
for (SECTION_LIST::iterator iter = ParentSection.begin(); iter != ParentSection.end(); iter++)
{
if (!IsAllParentLoops(*iter,false,GetNewTestValue()))
{
KillMe = false;
break;
}
}
if (KillMe)
{
delete this;
}
}
}
CCodeSection::~CCodeSection ( void )
{
while (ParentSection.size() > 0)
{
CCodeSection * Parent = *ParentSection.begin();
if (Parent->ContinueSection == this) { UnlinkParent(Parent, false, true); }
if (Parent->JumpSection == this) { UnlinkParent(Parent, false, false); }
}
if (ContinueSection)
{
ContinueSection->UnlinkParent(this, true, true);
if (ContinueSection)
{
_Notify->BreakPoint(__FILE__,__LINE__);
}
ContinueSection = NULL;
}
if (JumpSection)
{
JumpSection->UnlinkParent(this, true, false);
if (JumpSection)
{
_Notify->BreakPoint(__FILE__,__LINE__);
}
JumpSection = NULL;
}
}
DWORD CCodeSection::GetNewTestValue(void)
{
static DWORD LastTest = 0;
if (LastTest == 0xFFFFFFFF) { LastTest = 0; }
LastTest += 1;
return LastTest;
}
void CRegInfo::Initilize ( void )
{
int count;
MIPS_RegState[0] = STATE_CONST_32;
MIPS_RegVal[0].DW = 0;
for (count = 1; count < 32; count ++ ) {
MIPS_RegState[count] = STATE_UNKNOWN;
MIPS_RegVal[count].DW = 0;
}
for (count = 0; count < 10; count ++ ) {
x86reg_MappedTo[count] = NotMapped;
x86reg_Protected[count] = false;
x86reg_MapOrder[count] = 0;
}
CycleCount = 0;
RandomModifier = 0;
Stack_TopPos = 0;
for (count = 0; count < 8; count ++ ) {
x86fpu_MappedTo[count] = -1;
x86fpu_State[count] = FPU_Unkown;
x86fpu_RoundingModel[count] = RoundDefault;
}
Fpu_Used = false;
RoundingModel = RoundUnknown;
}
#endif
CRegInfo::REG_STATE CRegInfo::ConstantsType (__int64 Value)
{
if (((Value >> 32) == -1) && ((Value & 0x80000000) != 0)) { return STATE_CONST_32; }
if (((Value >> 32) == 0) && ((Value & 0x80000000) == 0)) { return STATE_CONST_32; }
return STATE_CONST_64;
}
bool CRegInfo::compare(const CRegInfo& right) const
{
int count;
for (count = 0; count < 32; count ++ ) {
if (MIPS_RegState[count] != right.MIPS_RegState[count])
{
return false;
}
if (MIPS_RegState[count] == STATE_UNKNOWN)
{
continue;
}
if (MIPS_RegVal[count].DW != right.MIPS_RegVal[count].DW)
{
return false;
}
}
for (count = 0; count < 10; count ++ ) {
if (x86reg_MappedTo[count] != right.x86reg_MappedTo[count]) { return false; }
if (x86reg_Protected[count] != right.x86reg_Protected[count]) { return false; }
if (x86reg_MapOrder[count] != right.x86reg_MapOrder[count]) { return false; }
}
if (m_CycleCount != right.m_CycleCount) { return false; }
if (Stack_TopPos != right.Stack_TopPos) { return false; }
for (count = 0; count < 8; count ++ ) {
if (x86fpu_MappedTo[count] != right.x86fpu_MappedTo[count]) { return false; }
if (x86fpu_State[count] != right.x86fpu_State[count]) { return false; }
if (x86fpu_RoundingModel[count] != right.x86fpu_RoundingModel[count]) { return false; }
}
if (Fpu_Used != right.Fpu_Used) { return false; }
if (GetRoundingModel() != right.GetRoundingModel()) { return false; }
return true;
}
bool CRegInfo::operator!=(const CRegInfo& right) const
{
return !compare(right);
}