diff --git a/Source/Project64/N64 System/Recompiler/Code Block.cpp b/Source/Project64/N64 System/Recompiler/Code Block.cpp index 91f3e5e7b..347d8c64e 100644 --- a/Source/Project64/N64 System/Recompiler/Code Block.cpp +++ b/Source/Project64/N64 System/Recompiler/Code Block.cpp @@ -1,5 +1,7 @@ #include "stdafx.h" +int DelaySlotEffectsCompare (DWORD PC, DWORD Reg1, DWORD Reg2); + CCodeBlock::CCodeBlock(DWORD VAddrEnter, BYTE * RecompPos) : m_VAddrEnter(VAddrEnter), m_VAddrFirst(VAddrEnter), @@ -169,6 +171,12 @@ bool CCodeBlock::CreateBlockLinkage ( CCodeSection * EnterSection ) return false; } + if (TestPC + 4 == EndPC && IncludeDelaySlot) + { + TargetPC = (DWORD)-1; + ContinuePC = (DWORD)-1; + EndBlock = true; + } if (TargetPC == (DWORD)-1 && !EndBlock) { if (ContinuePC != (DWORD)-1) @@ -288,9 +296,9 @@ bool CCodeBlock::CreateBlockLinkage ( CCodeSection * EnterSection ) } } - for (SectionList::iterator itr = m_Sections.begin(); itr != m_Sections.end(); itr++) + for (SectionMap::iterator itr = m_SectionMap.begin(); itr != m_SectionMap.end(); itr++) { - CCodeSection * Section = *itr; + CCodeSection * Section = itr->second; if (Section->m_JumpSection != NULL || Section->m_ContinueSection != NULL || Section->m_EndSection) @@ -555,13 +563,17 @@ bool CCodeBlock::AnalyzeInstruction ( DWORD PC, DWORD & TargetPC, DWORD & Contin LikelyBranch = true; break; case R4300i_BNEL: + case R4300i_BLEZL: case R4300i_BGTZL: TargetPC = PC + ((short)Command.offset << 2) + 4; + ContinuePC = PC + 8; if (TargetPC == PC) { - _Notify->BreakPoint(__FILE__,__LINE__); + if (!DelaySlotEffectsCompare(PC,Command.rs,Command.rt)) + { + PermLoop = true; + } } - ContinuePC = PC + 8; LikelyBranch = true; IncludeDelaySlot = true; break; diff --git a/Source/Project64/N64 System/Recompiler/Loop Analysis.cpp b/Source/Project64/N64 System/Recompiler/Loop Analysis.cpp index 40e8d3bdd..4ea6c059f 100644 --- a/Source/Project64/N64 System/Recompiler/Loop Analysis.cpp +++ b/Source/Project64/N64 System/Recompiler/Loop Analysis.cpp @@ -9,8 +9,7 @@ LoopAnalysis::LoopAnalysis(CCodeBlock * CodeBlock, CCodeSection * Section) : m_BlockInfo(CodeBlock), m_PC((DWORD)-1), m_NextInstruction(NORMAL), - m_Test(m_BlockInfo->NextTest()), - m_TestChanged(0) + m_Test(m_BlockInfo->NextTest()) { memset(&m_Command,0,sizeof(m_Command)); } @@ -43,13 +42,10 @@ bool LoopAnalysis::SetupRegisterForLoop ( void ) return false; } CPU_Message(__FUNCTION__ ": Section ID: %d Test: %X",m_EnterSection->m_SectionID,m_Test); - do + if (!CheckLoopRegisterUsage(m_EnterSection)) { - if (!CheckLoopRegisterUsage(m_EnterSection)) - { - return false; - } - } while (m_EnterSection->m_Test != m_Test); + return false; + } RegisterMap::iterator itr = m_EnterRegisters.find(m_EnterSection->m_SectionID); if (itr == m_EnterRegisters.end()) @@ -60,13 +56,15 @@ bool LoopAnalysis::SetupRegisterForLoop ( void ) return true; } -bool LoopAnalysis::SetupEnterSection ( CCodeSection * Section ) +bool LoopAnalysis::SetupEnterSection ( CCodeSection * Section, bool & bChanged, bool & bSkipedSection ) { + bChanged = false; + bSkipedSection = false; if (Section->m_ParentSection.empty()) { _Notify->BreakPoint(__FILE__,__LINE__); return true; } CPU_Message(__FUNCTION__ ": Block EnterPC: %X Section ID %d Test: %X Section Test: %X CompiledLocation: %X",m_BlockInfo->VAddrEnter(),Section->m_SectionID,m_Test,Section->m_Test, Section->m_CompiledLocation); - bool bFirstParent = true, bSkipedSection = false; + bool bFirstParent = true; CRegInfo RegEnter; for (CCodeSection::SECTION_LIST::iterator iter = Section->m_ParentSection.begin(); iter != Section->m_ParentSection.end(); iter++) { @@ -116,12 +114,7 @@ bool LoopAnalysis::SetupEnterSection ( CCodeSection * Section ) { if (SyncRegState(*(itr->second),RegEnter)) { - m_Test = m_BlockInfo->NextTest(); - m_TestChanged += 1; - if (m_TestChanged > MAX_TESTCHANGED) - { - _Notify->BreakPoint(__FILE__,__LINE__); - } + bChanged = true; } } else { m_EnterRegisters.insert(RegisterMap::value_type(Section->m_SectionID,new CRegInfo(RegEnter))); @@ -134,13 +127,22 @@ bool LoopAnalysis::CheckLoopRegisterUsage( CCodeSection * Section) if (Section == NULL) { return true; } if (!Section->m_InLoop) { return true; } - if (Section->m_Test == m_Test) + CPU_Message(__FUNCTION__ ": Section %d Block PC: 0x%X",Section->m_SectionID,m_BlockInfo->VAddrEnter()); + + bool bChanged = false, bSkipedSection = false; + if (Section == m_EnterSection && Section->m_Test == m_Test) + { + if (!SetupEnterSection(Section,bChanged,bSkipedSection)) { return false; } + return true; + } + + if (!SetupEnterSection(Section,bChanged,bSkipedSection)) { return false; } + + if (Section->m_Test == m_Test && !bChanged) { return true; } - if (!SetupEnterSection(Section)) { return false; } - CPU_Message(__FUNCTION__ ": Set Section %d test to %X from %X",Section->m_SectionID,m_Test,Section->m_Test); Section->m_Test = m_Test; m_PC = Section->m_EnterPC; @@ -157,9 +159,9 @@ bool LoopAnalysis::CheckLoopRegisterUsage( CCodeSection * Section) { _Notify->BreakPoint(__FILE__,__LINE__); return false; - } + } CPU_Message(" %08X: %s",m_PC,R4300iOpcodeName(m_Command.Hex,m_PC)); - CPU_Message(" %s state: %X value: %X",CRegName::GPR[1],m_Reg.MipsRegState(1),m_Reg.MipsRegLo(1)); + CPU_Message(" %s state: %X value: %X",CRegName::GPR[5],m_Reg.MipsRegState(5),m_Reg.MipsRegLo(5)); switch (m_Command.op) { case R4300i_SPECIAL: switch (m_Command.funct) { @@ -623,16 +625,10 @@ bool LoopAnalysis::CheckLoopRegisterUsage( CCodeSection * Section) }*/ if (m_PC == m_PC + ((short)m_Command.offset << 2) + 4) { - _Notify->BreakPoint(__FILE__,__LINE__); -#ifdef tofix - if (!DelaySlotEffectsCompare(m_PC,m_Command.rs,m_Command.rt)) + if (!DelaySlotEffectsCompare(m_PC,m_Command.rs,m_Command.rt) && !Section->m_Jump.PermLoop) { - if (!Section->m_Jump.PermLoop) - { - _Notify->BreakPoint(__FILE__,__LINE__); - } + _Notify->BreakPoint(__FILE__,__LINE__); } -#endif } #endif break; @@ -700,6 +696,8 @@ bool LoopAnalysis::CheckLoopRegisterUsage( CCodeSection * Section) R4300iOpcodeName(m_Command.Hex,m_PC),m_Command.Hex); } + CPU_Message(" %s state: %X value: %X",CRegName::GPR[5],m_Reg.MipsRegState(5),m_Reg.MipsRegLo(5)); + if (Section->m_DelaySlot) { if (m_NextInstruction != NORMAL) { _Notify->BreakPoint(__FILE__,__LINE__); } @@ -713,6 +711,10 @@ bool LoopAnalysis::CheckLoopRegisterUsage( CCodeSection * Section) case DELAY_SLOT: m_NextInstruction = DELAY_SLOT_DONE; m_PC += 4; + if ((m_PC & 0xFFFFF000) != (m_EnterSection->m_EnterPC & 0xFFFFF000)) + { + _Notify->BreakPoint(__FILE__,__LINE__); + } break; case LIKELY_DELAY_SLOT: { @@ -758,12 +760,10 @@ bool LoopAnalysis::CheckLoopRegisterUsage( CCodeSection * Section) if (!CheckLoopRegisterUsage(Section->m_ContinueSection)) { return false; } if (!CheckLoopRegisterUsage(Section->m_JumpSection)) { return false; } - - if (!SetupEnterSection(Section)) { return false; } return true; } -bool LoopAnalysis::SyncRegState ( CRegInfo & RegSet, const CRegInfo SyncReg ) +bool LoopAnalysis::SyncRegState ( CRegInfo & RegSet, const CRegInfo& SyncReg ) { bool bChanged = false; for (int x = 0; x < 32; x++) @@ -772,11 +772,13 @@ bool LoopAnalysis::SyncRegState ( CRegInfo & RegSet, const CRegInfo SyncReg ) { CPU_Message(__FUNCTION__ ": Clear state %s RegEnter State: %X Jump Reg State: %X",CRegName::GPR[x],RegSet.MipsRegState(x),SyncReg.MipsRegState(x)); RegSet.SetMipsRegState(x,CRegInfo::STATE_UNKNOWN); + bChanged = true; } else if (RegSet.IsConst(x) && RegSet.Is32Bit(x) && RegSet.cMipsRegLo(x) != SyncReg.cMipsRegLo(x)) { CPU_Message(__FUNCTION__ ": Clear state %s RegEnter State: %X Jump Reg State: %X",CRegName::GPR[x],RegSet.MipsRegState(x),SyncReg.MipsRegState(x)); - RegSet.SetMipsRegState(x,CRegInfo::STATE_UNKNOWN); + RegSet.SetMipsRegState(x,CRegInfo::STATE_UNKNOWN); + bChanged = true; } else if (RegSet.IsConst(x) && RegSet.Is64Bit(x)) { _Notify->BreakPoint(__FILE__,__LINE__); } diff --git a/Source/Project64/N64 System/Recompiler/Loop Analysis.h b/Source/Project64/N64 System/Recompiler/Loop Analysis.h index 89debb2d2..249638757 100644 --- a/Source/Project64/N64 System/Recompiler/Loop Analysis.h +++ b/Source/Project64/N64 System/Recompiler/Loop Analysis.h @@ -5,7 +5,6 @@ class CCodeBlock; class LoopAnalysis { - enum { MAX_TESTCHANGED = 1000 }; public: LoopAnalysis(CCodeBlock * CodeBlock, CCodeSection * Section); ~LoopAnalysis(); @@ -17,9 +16,9 @@ private: LoopAnalysis(const LoopAnalysis&); // Disable copy constructor LoopAnalysis& operator=(const LoopAnalysis&); // Disable assignment - bool SetupEnterSection ( CCodeSection * Section ); + bool SetupEnterSection ( CCodeSection * Section, bool & bChanged, bool & bSkipedSection ); bool CheckLoopRegisterUsage ( CCodeSection * Section ); - bool SyncRegState ( CRegInfo & RegSet, const CRegInfo SyncReg ); + bool SyncRegState ( CRegInfo & RegSet, const CRegInfo& SyncReg ); void SetJumpRegSet ( CCodeSection * Section, const CRegInfo &Reg ); void SetContinueRegSet ( CCodeSection * Section, const CRegInfo &Reg ); @@ -74,5 +73,4 @@ private: STEP_TYPE m_NextInstruction; OPCODE m_Command; DWORD m_Test; - DWORD m_TestChanged; }; \ No newline at end of file diff --git a/Source/Project64/N64 System/Recompiler/Recompiler Ops.cpp b/Source/Project64/N64 System/Recompiler/Recompiler Ops.cpp index e2c0826f2..a06d5ed67 100644 --- a/Source/Project64/N64 System/Recompiler/Recompiler Ops.cpp +++ b/Source/Project64/N64 System/Recompiler/Recompiler Ops.cpp @@ -1993,24 +1993,13 @@ void CRecompilerOps::SPECIAL_JR (void) { return; } - if (IsConst(m_Opcode.rs)) { - m_Section->m_Jump.BranchLabel.Format("0x%08X",cMipsRegLo(m_Opcode.rs)); - m_Section->m_Jump.TargetPC = cMipsRegLo(m_Opcode.rs); - m_Section->m_Jump.JumpPC = m_Section->m_Jump.TargetPC + 4; - m_Section->m_Jump.FallThrough = TRUE; - m_Section->m_Jump.LinkLocation = NULL; - m_Section->m_Jump.LinkLocation2 = NULL; - m_Section->m_Cont.FallThrough = FALSE; - m_Section->m_Cont.LinkLocation = NULL; - m_Section->m_Cont.LinkLocation2 = NULL; - } else { - m_Section->m_Jump.FallThrough = false; - m_Section->m_Jump.LinkLocation = NULL; - m_Section->m_Jump.LinkLocation2 = NULL; - m_Section->m_Cont.FallThrough = FALSE; - m_Section->m_Cont.LinkLocation = NULL; - m_Section->m_Cont.LinkLocation2 = NULL; - } + m_Section->m_Jump.FallThrough = false; + m_Section->m_Jump.LinkLocation = NULL; + m_Section->m_Jump.LinkLocation2 = NULL; + m_Section->m_Cont.FallThrough = FALSE; + m_Section->m_Cont.LinkLocation = NULL; + m_Section->m_Cont.LinkLocation2 = NULL; + if (DelaySlotEffectsCompare(m_CompilePC,m_Opcode.rs,0)) { if (IsConst(m_Opcode.rs)) { MoveConstToVariable(cMipsRegLo(m_Opcode.rs),_PROGRAM_COUNTER, "PROGRAM_COUNTER"); @@ -2027,20 +2016,16 @@ void CRecompilerOps::SPECIAL_JR (void) { } else { UpdateCounters(m_RegWorkingSet,true,true); if (IsConst(m_Opcode.rs)) { - m_Section->m_Jump.JumpPC = m_Section->m_Jump.TargetPC + 4; - m_Section->m_Jump.RegSet = m_RegWorkingSet; - m_Section->GenerateSectionLinkage(); + MoveConstToVariable(cMipsRegLo(m_Opcode.rs),_PROGRAM_COUNTER, "PROGRAM_COUNTER"); + } else if (IsMapped(m_Opcode.rs)) { + MoveX86regToVariable(MipsRegMapLo(m_Opcode.rs),_PROGRAM_COUNTER, "PROGRAM_COUNTER"); } else { - if (IsMapped(m_Opcode.rs)) { - MoveX86regToVariable(MipsRegMapLo(m_Opcode.rs),_PROGRAM_COUNTER, "PROGRAM_COUNTER"); - } else { - MoveX86regToVariable(Map_TempReg(x86_Any,m_Opcode.rs,FALSE),_PROGRAM_COUNTER, "PROGRAM_COUNTER"); - } - m_Section->CompileExit((DWORD)-1, (DWORD)-1,m_RegWorkingSet,CExitInfo::Normal,TRUE,NULL); - if (m_Section->m_JumpSection) - { - m_Section->GenerateSectionLinkage(); - } + MoveX86regToVariable(Map_TempReg(x86_Any,m_Opcode.rs,FALSE),_PROGRAM_COUNTER, "PROGRAM_COUNTER"); + } + m_Section->CompileExit((DWORD)-1, (DWORD)-1,m_RegWorkingSet,CExitInfo::Normal,TRUE,NULL); + if (m_Section->m_JumpSection) + { + m_Section->GenerateSectionLinkage(); } } m_NextInstruction = END_BLOCK;