From f52f82e8b53d0672ab0d94d222f6264601d6c034 Mon Sep 17 00:00:00 2001 From: zilmar Date: Tue, 25 Sep 2012 15:58:06 +1000 Subject: [PATCH] Changed handling of delay slot which goes over a 4k boundary to be executed by the interpret code instead of trying to be compiler. This means we do not have to care about the self mod of the delay slot --- Source/Project64/N64 System/N64 Class.cpp | 15 +- Source/Project64/N64 System/N64 Class.h | 3 + .../N64 System/Recompiler/Code Block.cpp | 51 ++--- .../N64 System/Recompiler/Code Block.h | 4 +- .../N64 System/Recompiler/Code Section.cpp | 17 +- .../N64 System/Recompiler/Code Section.h | 5 - .../Recompiler/Recompiler Class.cpp | 68 +------ .../N64 System/Recompiler/Recompiler Class.h | 1 - .../N64 System/Recompiler/Recompiler Ops.cpp | 182 +++++++++++++----- .../N64 System/Recompiler/Recompiler Ops.h | 2 + 10 files changed, 175 insertions(+), 173 deletions(-) diff --git a/Source/Project64/N64 System/N64 Class.cpp b/Source/Project64/N64 System/N64 Class.cpp index 478d897bd..a58be00cc 100644 --- a/Source/Project64/N64 System/N64 Class.cpp +++ b/Source/Project64/N64 System/N64 Class.cpp @@ -44,7 +44,10 @@ CN64System::CN64System ( CPlugins * Plugins, bool SavesReadOnly ) : m_SystemTimer(m_NextTimer), m_DMAUsed(false), m_CPU_Handle(NULL), - m_CPU_ThreadID(0) + m_CPU_ThreadID(0), + m_TestTimer(false), + m_NextInstruction(0), + m_JumpToLocation(0) { m_hPauseEvent = CreateEvent(NULL,true,false,NULL); m_Limitor.SetHertz(_Settings->LoadDword(Game_ScreenHertz)); @@ -522,6 +525,13 @@ bool CN64System::SetActiveSystem( bool bActive ) { m_Reg.SetAsCurrentSystem(); + if (_System) + { + _System->m_TestTimer = R4300iOp::m_TestTimer; + _System->m_NextInstruction = R4300iOp::m_NextInstruction; + _System->m_JumpToLocation = R4300iOp::m_JumpToLocation; + } + _System = this; if (_BaseSystem == this) { @@ -538,6 +548,9 @@ bool CN64System::SetActiveSystem( bool bActive ) _SystemEvents = this; _NextTimer = &m_NextTimer; _Plugins = m_Plugins; + R4300iOp::m_TestTimer = m_TestTimer; + R4300iOp::m_NextInstruction = m_NextInstruction; + R4300iOp::m_JumpToLocation = m_JumpToLocation; if (!m_bInitilized) { diff --git a/Source/Project64/N64 System/N64 Class.h b/Source/Project64/N64 System/N64 Class.h index a2cd809e0..1773b4d24 100644 --- a/Source/Project64/N64 System/N64 Class.h +++ b/Source/Project64/N64 System/N64 Class.h @@ -125,6 +125,9 @@ private: int m_NextTimer; bool m_DMAUsed; DWORD m_Buttons[4]; + BOOL m_TestTimer; + DWORD m_NextInstruction; + DWORD m_JumpToLocation; //When Syncing cores this is the PC where it last Sync'ed correctly DWORD m_LastSuccessSyncPC[10]; diff --git a/Source/Project64/N64 System/Recompiler/Code Block.cpp b/Source/Project64/N64 System/Recompiler/Code Block.cpp index 3b80cdd28..7812fbe9d 100644 --- a/Source/Project64/N64 System/Recompiler/Code Block.cpp +++ b/Source/Project64/N64 System/Recompiler/Code Block.cpp @@ -1,13 +1,12 @@ #include "stdafx.h" -CCodeBlock::CCodeBlock(DWORD VAddrEnter, BYTE * RecompPos, bool bDelaySlot) : +CCodeBlock::CCodeBlock(DWORD VAddrEnter, BYTE * RecompPos) : m_VAddrEnter(VAddrEnter), m_VAddrFirst(VAddrEnter), m_VAddrLast(VAddrEnter), m_CompiledLocation(RecompPos), m_NoOfSections(1), m_EnterSection(this, VAddrEnter, 1), - m_bDelaySlot(bDelaySlot), m_Test(1) { if (_TransVaddr->VAddrToRealAddr(VAddrEnter,*(reinterpret_cast(&m_MemLocation[0])))) @@ -35,46 +34,30 @@ bool CCodeBlock::AnalyseBlock ( void ) bool CCodeBlock::Compile() { - if (m_bDelaySlot) - { - CPU_Message("====== Delay Block ======"); - } else { - CPU_Message("====== Code Block ======"); - } + 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(); + EnterCodeBlock(); + + /*if (bLinkBlocks()) { + for (int i = 0; i < m_NoOfSections; i ++) { + m_EnterSection.DisplaySectionInformation(i + 1,NextTest()); + } + }*/ + if (_SyncSystem) { + //if ((DWORD)BlockInfo.CompiledLocation == 0x60A7B73B) { X86BreakPoint(__FILE__,__LINE__); } + //MoveConstToVariable((DWORD)BlockInfo.CompiledLocation,&CurrentBlock,"CurrentBlock"); } - if (m_bDelaySlot) - { - m_EnterSection.GenerateX86Code(NextTest()); + if (bLinkBlocks()) { + while (m_EnterSection.GenerateX86Code(NextTest())); } else { - /*if (bLinkBlocks()) { - for (int i = 0; i < m_NoOfSections; i ++) { - m_EnterSection.DisplaySectionInformation(i + 1,NextTest()); - } - }*/ - if (_SyncSystem) { - //if ((DWORD)BlockInfo.CompiledLocation == 0x60A7B73B) { X86BreakPoint(__FILE__,__LINE__); } - //MoveConstToVariable((DWORD)BlockInfo.CompiledLocation,&CurrentBlock,"CurrentBlock"); - } - - if (bLinkBlocks()) { - while (m_EnterSection.GenerateX86Code(NextTest())); - } else { - if (!m_EnterSection.GenerateX86Code(NextTest())) - { - return false; - } + if (!m_EnterSection.GenerateX86Code(NextTest())) + { + return false; } } CompileExitCode(); diff --git a/Source/Project64/N64 System/Recompiler/Code Block.h b/Source/Project64/N64 System/Recompiler/Code Block.h index 89316c81e..302f15d15 100644 --- a/Source/Project64/N64 System/Recompiler/Code Block.h +++ b/Source/Project64/N64 System/Recompiler/Code Block.h @@ -2,7 +2,7 @@ class CCodeBlock : private CRecompilerOps { public: - CCodeBlock(DWORD VAddrEnter, BYTE * RecompPos, bool bDelaySlot ); + CCodeBlock(DWORD VAddrEnter, BYTE * RecompPos ); bool Compile ( void ); @@ -12,7 +12,6 @@ public: inline BYTE * CompiledLocation ( void ) const { return m_CompiledLocation; } inline int NoOfSections ( void ) const { return m_NoOfSections; } inline const CCodeSection & EnterSection ( void ) const { return m_EnterSection; } - inline bool bDelaySlot ( void ) const { return m_bDelaySlot; } inline const MD5Digest & Hash ( void ) const { return m_Hash; } inline void SetVAddrFirst ( DWORD VAddr ) { m_VAddrFirst = VAddr; } @@ -38,7 +37,6 @@ private: DWORD m_VAddrLast; // the address of the first opcode in the block BYTE * m_CompiledLocation; // What address is this compiled at int m_NoOfSections; // The number of sections this block uses - bool m_bDelaySlot; CCodeSection m_EnterSection; DWORD m_Test; MD5Digest m_Hash; diff --git a/Source/Project64/N64 System/Recompiler/Code Section.cpp b/Source/Project64/N64 System/Recompiler/Code Section.cpp index 7f5bce5fa..947c849f6 100644 --- a/Source/Project64/N64 System/Recompiler/Code Section.cpp +++ b/Source/Project64/N64 System/Recompiler/Code Section.cpp @@ -82,7 +82,6 @@ CCodeSection::CCodeSection( CCodeBlock * CodeBlock, DWORD EnterPC, DWORD ID) : m_JumpSection(NULL), m_LinkAllowed(true), m_CompiledLocation(NULL), - m_DelaySlotSection(CodeBlock? CodeBlock->bDelaySlot() : false), m_Test(0), m_Test2(0), m_InLoop(false) @@ -313,6 +312,8 @@ void CCodeSection::GenerateSectionLinkage (void) } if ((CompilePC() & 0xFFC) == 0xFFC) { + _Notify->BreakPoint(__FILE__,__LINE__); +#ifdef tofix //Handle Fall througth BYTE * Jump = NULL; for (i = 0; i < 2; i ++) { @@ -366,6 +367,7 @@ void CCodeSection::GenerateSectionLinkage (void) JmpDirectReg(x86_EAX); ExitCodeBlock(); return; +#endif } if (!g_UseLinking) { if (CRecompilerOps::m_CompilePC == m_Jump.TargetPC && (m_Cont.FallThrough == false)) { @@ -907,14 +909,9 @@ bool CCodeSection::GenerateX86Code ( DWORD Test ) m_RegWorkingSet = m_RegEnter; m_CompiledLocation = m_RecompPos; m_CompilePC = m_EnterPC; - m_NextInstruction = m_DelaySlotSection ? END_BLOCK : NORMAL; + m_NextInstruction = NORMAL; m_Section = this; - if (m_DelaySlotSection) - { - m_Cont.JumpPC = m_EnterPC; - } - if (m_CompilePC < m_BlockInfo->VAddrFirst()) { m_BlockInfo->SetVAddrFirst(m_CompilePC); @@ -1250,6 +1247,7 @@ bool CCodeSection::GenerateX86Code ( DWORD Test ) if (m_NextInstruction == DO_DELAY_SLOT) { DisplayError("Wanting to do delay slot over end of block"); + _Notify->BreakPoint(__FILE__,__LINE__); } if (m_NextInstruction == NORMAL) { CompileExit (m_CompilePC, m_CompilePC + 4,m_RegWorkingSet,CExitInfo::Normal,true,NULL); @@ -1272,11 +1270,6 @@ bool CCodeSection::GenerateX86Code ( DWORD Test ) break; } } while (m_NextInstruction != END_BLOCK); - - if (m_DelaySlotSection) - { - CompileExit (m_CompilePC, -1,m_RegWorkingSet,CExitInfo::Normal,true,NULL); - } return true; } diff --git a/Source/Project64/N64 System/Recompiler/Code Section.h b/Source/Project64/N64 System/Recompiler/Code Section.h index f06dc9a99..a9b70d27f 100644 --- a/Source/Project64/N64 System/Recompiler/Code Section.h +++ b/Source/Project64/N64 System/Recompiler/Code Section.h @@ -34,12 +34,8 @@ public: DWORD m_Test; DWORD m_Test2; BYTE * m_CompiledLocation; - bool m_DelaySlotSection; bool m_InLoop; - /* - - /* Register Info */ CRegInfo m_RegEnter; @@ -47,7 +43,6 @@ public: CJumpInfo m_Jump; CJumpInfo m_Cont; - private: void AddParent ( CCodeSection * Parent ); void UnlinkParent ( CCodeSection * Parent, bool ContinueSection ); diff --git a/Source/Project64/N64 System/Recompiler/Recompiler Class.cpp b/Source/Project64/N64 System/Recompiler/Recompiler Class.cpp index fb8364d01..be0660224 100644 --- a/Source/Project64/N64 System/Recompiler/Recompiler Class.cpp +++ b/Source/Project64/N64 System/Recompiler/Recompiler Class.cpp @@ -677,72 +677,6 @@ void CRecompiler::ResetRecompCode() m_Functions.clear(); } -BYTE * CRecompiler::CompileDelaySlot(DWORD PC) -{ - if (LookUpMode() == FuncFind_VirtualLookup) - { - int Index = PC >> 0xC; - BYTE * delayFunc = DelaySlotTable()[Index]; - if (delayFunc) - { - return delayFunc; - } - - WriteTraceF(TraceRecompiler,"Compile Delay Slot: %X",PC); - if ((PC & 0xFFC) != 0) { - DisplayError("Why are you compiling the Delay Slot at %X",PC); - return NULL; - } - - CheckRecompMem(); - - CCodeBlock CodeBlock(PC, RecompPos(), true); - if (!CodeBlock.Compile()) - { - return NULL; - } - - CCompiledFunc * Func = new CCompiledFunc(CodeBlock); - delayFunc = (BYTE *)Func->Function(); - DelaySlotTable()[Index] = delayFunc; - delete Func; - return delayFunc; - } else { - DWORD pAddr; - if (_TransVaddr->TranslateVaddr(PC,pAddr)) - { - int Index = pAddr >> 0xC; - BYTE * delayFunc = DelaySlotTable()[Index]; - if (delayFunc) - { - return delayFunc; - } - WriteTraceF(TraceRecompiler,"Compile Delay Slot: %X",pAddr); - if ((pAddr & 0xFFC) != 0) { - DisplayError("Why are you compiling the Delay Slot at %X",pAddr); - return NULL; - } - - CheckRecompMem(); - - CCodeBlock CodeBlock(PC, RecompPos(), true); - if (!CodeBlock.Compile()) - { - return NULL; - } - - CCompiledFunc * Func = new CCompiledFunc(CodeBlock); - delayFunc = (BYTE *)Func->Function(); - DelaySlotTable()[Index] = delayFunc; - delete Func; - return delayFunc; - } else { - _Notify->BreakPoint(__FILE__,__LINE__); - } - return NULL; - } -} - void CRecompiler::RecompilerMain_ChangeMemory ( void ) { _Notify->BreakPoint(__FILE__,__LINE__); @@ -916,7 +850,7 @@ CCompiledFunc * CRecompiler::CompilerCode ( void ) DWORD StartTime = timeGetTime(); WriteTraceF(TraceRecompiler,"Compile Block-Start: Program Counter: %X pAddr: %X",PROGRAM_COUNTER,pAddr); - CCodeBlock CodeBlock(PROGRAM_COUNTER, RecompPos(),false); + CCodeBlock CodeBlock(PROGRAM_COUNTER, RecompPos()); if (!CodeBlock.Compile()) { return NULL; diff --git a/Source/Project64/N64 System/Recompiler/Recompiler Class.h b/Source/Project64/N64 System/Recompiler/Recompiler Class.h index 2b7c61cea..9bc063b46 100644 --- a/Source/Project64/N64 System/Recompiler/Recompiler Class.h +++ b/Source/Project64/N64 System/Recompiler/Recompiler Class.h @@ -28,7 +28,6 @@ public: void ResetRecompCode ( void ); bool GenerateX86Code (CCodeBlock & BlockInfo, CCodeSection * Section, DWORD Test ); - BYTE * CompileDelaySlot ( DWORD PC ); //Self modifying code methods void ClearRecompCode_Virt ( DWORD VirtualAddress, int length, REMOVE_REASON Reason ); diff --git a/Source/Project64/N64 System/Recompiler/Recompiler Ops.cpp b/Source/Project64/N64 System/Recompiler/Recompiler Ops.cpp index acb91532d..3c662ddc1 100644 --- a/Source/Project64/N64 System/Recompiler/Recompiler Ops.cpp +++ b/Source/Project64/N64 System/Recompiler/Recompiler Ops.cpp @@ -36,7 +36,8 @@ void CRecompilerOps::Compile_Branch (CRecompilerOps::BranchFunction CompareFunc, if ( m_NextInstruction == NORMAL ) { CPU_Message(" %X %s",m_CompilePC,R4300iOpcodeName(m_Opcode.Hex,m_CompilePC)); - if ((m_CompilePC & 0xFFC) != 0xFFC) { + if ((m_CompilePC & 0xFFC) != 0xFFC) + { switch (BranchType) { case BranchTypeRs: EffectDelaySlot = DelaySlotEffectsCompare(m_CompilePC,m_Opcode.rs,0); break; case BranchTypeRsRt: EffectDelaySlot = DelaySlotEffectsCompare(m_CompilePC,m_Opcode.rs,m_Opcode.rt); break; @@ -66,7 +67,7 @@ void CRecompilerOps::Compile_Branch (CRecompilerOps::BranchFunction CompareFunc, #endif } } else { - EffectDelaySlot = TRUE; + EffectDelaySlot = true; } m_Section->m_Jump.JumpPC = m_CompilePC; m_Section->m_Jump.TargetPC = m_CompilePC + ((short)m_Opcode.offset << 2) + 4; @@ -95,10 +96,6 @@ void CRecompilerOps::Compile_Branch (CRecompilerOps::BranchFunction CompareFunc, m_Section->m_Cont.FallThrough = TRUE; m_Section->m_Jump.FallThrough = FALSE; } - if (m_Section->m_Jump.TargetPC == m_Section->m_Cont.TargetPC) - { - EffectDelaySlot = (m_CompilePC & 0xFFC) == 0xFFC; - } if (Link) { UnMap_GPR( 31, FALSE); @@ -106,17 +103,18 @@ void CRecompilerOps::Compile_Branch (CRecompilerOps::BranchFunction CompareFunc, MipsRegState(31) = CRegInfo::STATE_CONST_32; } if (EffectDelaySlot) { - m_Section->m_Cont.BranchLabel = m_Section->m_ContinueSection != NULL ? "Continue" : "ExitBlock"; - m_Section->m_Jump.BranchLabel = m_Section->m_JumpSection != NULL ? "Jump" : "ExitBlock"; + if ((m_CompilePC & 0xFFC) != 0xFFC) + { + m_Section->m_Cont.BranchLabel = m_Section->m_ContinueSection != NULL ? "Continue" : "ExitBlock"; + m_Section->m_Jump.BranchLabel = m_Section->m_JumpSection != NULL ? "Jump" : "ExitBlock"; + } else { + m_Section->m_Cont.BranchLabel = "Continue"; + m_Section->m_Jump.BranchLabel = "Jump"; + } if (m_Section->m_Jump.TargetPC != m_Section->m_Cont.TargetPC) { CompareFunc(); } - if ((m_CompilePC & 0xFFC) == 0xFFC) { - m_Section->GenerateSectionLinkage(); - m_NextInstruction = END_BLOCK; - return; - } if (!m_Section->m_Jump.FallThrough && !m_Section->m_Cont.FallThrough) { if (m_Section->m_Jump.LinkLocation != NULL) { CPU_Message(""); @@ -140,6 +138,55 @@ void CRecompilerOps::Compile_Branch (CRecompilerOps::BranchFunction CompareFunc, m_Section->m_Cont.FallThrough = TRUE; } } + if ((m_CompilePC & 0xFFC) == 0xFFC) + { + BYTE * DelayLinkLocation = NULL; + if (m_Section->m_Jump.FallThrough) + { + if (m_Section->m_Jump.LinkLocation != NULL || m_Section->m_Jump.LinkLocation2 != NULL) + { + _Notify->BreakPoint(__FILE__,__LINE__); + } + MoveConstToVariable(m_Section->m_Jump.TargetPC,&R4300iOp::m_JumpToLocation,"R4300iOp::m_JumpToLocation"); + } + else if (m_Section->m_Cont.FallThrough) + { + if (m_Section->m_Cont.LinkLocation != NULL || m_Section->m_Cont.LinkLocation2 != NULL) + { + _Notify->BreakPoint(__FILE__,__LINE__); + } + MoveConstToVariable(m_Section->m_Cont.TargetPC,&R4300iOp::m_JumpToLocation,"R4300iOp::m_JumpToLocation"); + } + + if (m_Section->m_Jump.LinkLocation != NULL || m_Section->m_Jump.LinkLocation2 != NULL) + { + JmpLabel8("DoDelaySlot",0); + if (DelayLinkLocation != NULL) { _Notify->BreakPoint(__FILE__,__LINE__); } + DelayLinkLocation = (BYTE *)(m_RecompPos - 1); + + CPU_Message(" "); + CPU_Message(" %s:",m_Section->m_Jump.BranchLabel.c_str()); + SetJump32(m_Section->m_Jump.LinkLocation,(DWORD *)m_RecompPos); + m_Section->m_Jump.LinkLocation = NULL; + if (m_Section->m_Jump.LinkLocation2 != NULL) { + SetJump32(m_Section->m_Jump.LinkLocation2,(DWORD *)m_RecompPos); + m_Section->m_Jump.LinkLocation2 = NULL; + } + MoveConstToVariable(m_Section->m_Jump.TargetPC,&R4300iOp::m_JumpToLocation,"R4300iOp::m_JumpToLocation"); + } + if (m_Section->m_Cont.LinkLocation != NULL || m_Section->m_Cont.LinkLocation2 != NULL) + { + _Notify->BreakPoint(__FILE__,__LINE__); + } + if (DelayLinkLocation) + { + CPU_Message(""); + CPU_Message(" DoDelaySlot:"); + SetJump8(DelayLinkLocation,m_RecompPos); + } + OverflowDelaySlot(); + return; + } ResetX86Protection(); memcpy(&RegBeforeDelay,&m_RegWorkingSet,sizeof(CRegInfo)); } @@ -268,7 +315,8 @@ void CRecompilerOps::Compile_BranchLikely (BranchFunction CompareFunc, BOOL Link m_NextInstruction = END_BLOCK; } else { if ((m_CompilePC & 0xFFC) == 0xFFC) { - m_Section->m_Jump.FallThrough = FALSE; + if (m_Section->m_Cont.FallThrough) { _Notify->BreakPoint(__FILE__,__LINE__); } + if (m_Section->m_Jump.LinkLocation != NULL) { SetJump32(m_Section->m_Jump.LinkLocation,(DWORD *)m_RecompPos); m_Section->m_Jump.LinkLocation = NULL; @@ -277,8 +325,8 @@ void CRecompilerOps::Compile_BranchLikely (BranchFunction CompareFunc, BOOL Link m_Section->m_Jump.LinkLocation2 = NULL; } } - JmpLabel32("DoDelaySlot",0); - m_Section->m_Jump.LinkLocation = (DWORD *)(m_RecompPos - 4); + MoveConstToVariable(m_Section->m_Jump.TargetPC,&R4300iOp::m_JumpToLocation,"R4300iOp::m_JumpToLocation"); + OverflowDelaySlot(); CPU_Message(" "); CPU_Message(" %s:",m_Section->m_Cont.BranchLabel.c_str()); if (m_Section->m_Cont.LinkLocation != NULL) { @@ -290,10 +338,7 @@ void CRecompilerOps::Compile_BranchLikely (BranchFunction CompareFunc, BOOL Link } } m_Section->CompileExit(m_CompilePC, m_CompilePC + 8,m_Section->m_Cont.RegSet,CExitInfo::Normal,TRUE,NULL); - CPU_Message(""); - CPU_Message(" DoDelaySlot:"); - m_Section->GenerateSectionLinkage(); - m_NextInstruction = END_BLOCK; + return; } else { m_NextInstruction = DO_DELAY_SLOT; } @@ -1217,10 +1262,14 @@ void CRecompilerOps::J (void) { m_Section->m_Jump.LinkLocation = NULL; m_Section->m_Jump.LinkLocation2 = NULL; m_NextInstruction = DO_DELAY_SLOT; - if ((m_CompilePC & 0xFFC) == 0xFFC) { + if ((m_CompilePC & 0xFFC) == 0xFFC) + { + _Notify->BreakPoint(__FILE__,__LINE__); +#ifdef tofix memcpy(&m_Section->m_Jump.RegSet,&m_RegWorkingSet,sizeof(CRegInfo)); m_Section->GenerateSectionLinkage(); m_NextInstruction = END_BLOCK; +#endif } } else if (m_NextInstruction == DELAY_SLOT_DONE ) { m_Section->m_Jump.RegSet = m_RegWorkingSet; @@ -1239,7 +1288,13 @@ void CRecompilerOps::JAL (void) { UnMap_GPR( 31, FALSE); MipsRegLo(31) = m_CompilePC + 8; MipsRegState(31) = CRegInfo::STATE_CONST_32; - m_Section->m_Jump.TargetPC = (m_CompilePC & 0xF0000000) + (m_Opcode.target << 2); + if ((m_CompilePC & 0xFFC) == 0xFFC) + { + MoveConstToVariable((m_CompilePC & 0xF0000000) + (m_Opcode.target << 2),&R4300iOp::m_JumpToLocation,"R4300iOp::m_JumpToLocation"); + OverflowDelaySlot(); + return; + } + m_Section->m_Jump.TargetPC = (m_CompilePC & 0xF0000000) + (m_Opcode.target << 2); m_Section->m_Jump.JumpPC = m_CompilePC; if (m_Section->m_JumpSection != NULL) { m_Section->m_Jump.BranchLabel.Format("Section_%d",((CCodeSection *)m_Section->m_JumpSection)->m_SectionID); @@ -1249,14 +1304,7 @@ void CRecompilerOps::JAL (void) { m_Section->m_Jump.FallThrough = TRUE; m_Section->m_Jump.LinkLocation = NULL; m_Section->m_Jump.LinkLocation2 = NULL; - - if ((m_CompilePC & 0xFFC) == 0xFFC) - { - m_Section->GenerateSectionLinkage(); - m_NextInstruction = END_BLOCK; - } else { - m_NextInstruction = DO_DELAY_SLOT; - } + m_NextInstruction = DO_DELAY_SLOT; } else if (m_NextInstruction == DELAY_SLOT_DONE ) { if (m_Section->m_JumpSection) { @@ -1921,6 +1969,19 @@ void CRecompilerOps::SPECIAL_SRAV (void) { void CRecompilerOps::SPECIAL_JR (void) { if ( m_NextInstruction == NORMAL ) { CPU_Message(" %X %s",m_CompilePC,R4300iOpcodeName(m_Opcode.Hex,m_CompilePC)); + if ((m_CompilePC & 0xFFC) == 0xFFC) + { + if (IsMapped(m_Opcode.rs)) { + MoveX86regToVariable(cMipsRegMapLo(m_Opcode.rs),&R4300iOp::m_JumpToLocation,"R4300iOp::m_JumpToLocation"); + m_RegWorkingSet.WriteBackRegisters(); + } else { + m_RegWorkingSet.WriteBackRegisters(); + MoveX86regToVariable(Map_TempReg(x86_Any,m_Opcode.rs,FALSE),&R4300iOp::m_JumpToLocation,"R4300iOp::m_JumpToLocation"); + } + OverflowDelaySlot(); + 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); @@ -1932,8 +1993,11 @@ void CRecompilerOps::SPECIAL_JR (void) { m_Section->m_Cont.LinkLocation = NULL; m_Section->m_Cont.LinkLocation2 = NULL; if ((m_CompilePC & 0xFFC) == 0xFFC) { + _Notify->BreakPoint(__FILE__,__LINE__); +#ifdef tofix m_Section->GenerateSectionLinkage(); m_NextInstruction = END_BLOCK; +#endif return; } } else { @@ -1944,16 +2008,6 @@ void CRecompilerOps::SPECIAL_JR (void) { m_Section->m_Cont.LinkLocation = NULL; m_Section->m_Cont.LinkLocation2 = NULL; } - if ((m_CompilePC & 0xFFC) == 0xFFC) { - if (IsMapped(m_Opcode.rs)) { - Push(cMipsRegMapLo(m_Opcode.rs)); - } else { - Push(Map_TempReg(x86_Any,m_Opcode.rs,FALSE)); - } - m_Section->GenerateSectionLinkage(); - m_NextInstruction = END_BLOCK; - return; - } if (DelaySlotEffectsCompare(m_CompilePC,m_Opcode.rs,0)) { if (IsConst(m_Opcode.rs)) { MoveConstToVariable(cMipsRegLo(m_Opcode.rs),_PROGRAM_COUNTER, "PROGRAM_COUNTER"); @@ -2004,6 +2058,8 @@ void CRecompilerOps::SPECIAL_JALR (void) { MipsRegLo(m_Opcode.rd) = m_CompilePC + 8; MipsRegState(m_Opcode.rd) = CRegInfo::STATE_CONST_32; if ((m_CompilePC & 0xFFC) == 0xFFC) { + _Notify->BreakPoint(__FILE__,__LINE__); +#ifdef tofix if (IsMapped(m_Opcode.rs)) { Push(cMipsRegMapLo(m_Opcode.rs)); } else { @@ -2011,6 +2067,7 @@ void CRecompilerOps::SPECIAL_JALR (void) { } m_Section->GenerateSectionLinkage(); m_NextInstruction = END_BLOCK; +#endif return; } m_NextInstruction = DO_DELAY_SLOT; @@ -5043,20 +5100,27 @@ void CRecompilerOps::ExitCodeBlock ( void ) Ret(); } +void CRecompilerOps::UpdateSyncCPU ( CRegInfo & RegSet, DWORD Cycles ) +{ + if (!_SyncSystem) + { + return; + } + + WriteX86Comment("Updating Sync CPU"); + BeforeCallDirect(RegSet); + PushImm32(stdstr_f("%d",Cycles).c_str(),Cycles); + PushImm32("_SyncSystem",(DWORD)_SyncSystem); + MoveConstToX86reg((DWORD)_System,x86_ECX); + Call_Direct(AddressOf(&CN64System::UpdateSyncCPU),"CN64System::UpdateSyncCPU"); + AfterCallDirect(RegSet); +} + void CRecompilerOps::UpdateCounters ( CRegInfo & RegSet, bool CheckTimer, bool ClearValues ) { if (RegSet.GetBlockCycleCount() != 0) { - if (_SyncSystem) { - - WriteX86Comment("Updating Sync CPU"); - BeforeCallDirect(RegSet); - PushImm32(stdstr_f("%d",RegSet.GetBlockCycleCount()).c_str(),RegSet.GetBlockCycleCount()); - PushImm32("_SyncSystem",(DWORD)_SyncSystem); - MoveConstToX86reg((DWORD)_System,x86_ECX); - Call_Direct(AddressOf(&CN64System::UpdateSyncCPU),"CN64System::UpdateSyncCPU"); - AfterCallDirect(RegSet); - } + UpdateSyncCPU(RegSet,RegSet.GetBlockCycleCount()); WriteX86Comment("Update Counter"); SubConstFromVariable(RegSet.GetBlockCycleCount(),_NextTimer,"_NextTimer"); // updates compare flag if (ClearValues) @@ -5102,3 +5166,21 @@ void CRecompilerOps::CompileSystemCheck (DWORD TargetPC, CRegInfo RegSet) SetJump32(Jump,(DWORD *)m_RecompPos); } +void CRecompilerOps::OverflowDelaySlot (void) +{ + m_RegWorkingSet.WriteBackRegisters(); + UpdateCounters(m_RegWorkingSet,false,true); + MoveConstToVariable(CompilePC() + 4,_PROGRAM_COUNTER,"PROGRAM_COUNTER"); + if (_SyncSystem) { Call_Direct(SyncSystem, "SyncSystem"); } + MoveConstToVariable(JUMP,&R4300iOp::m_NextInstruction,"R4300iOp::m_NextInstruction"); + PushImm32("CountPerOp()",CountPerOp()); + Call_Direct(CInterpreterCPU::ExecuteOps, "CInterpreterCPU::ExecuteOps"); + AddConstToX86Reg(x86_ESP,4); + if (_SyncSystem) + { + UpdateSyncCPU(m_RegWorkingSet,g_CountPerOp); + Call_Direct(SyncSystem, "SyncSystem"); + } + ExitCodeBlock(); + m_NextInstruction = END_BLOCK; +} \ No newline at end of file diff --git a/Source/Project64/N64 System/Recompiler/Recompiler Ops.h b/Source/Project64/N64 System/Recompiler/Recompiler Ops.h index 5cf26f2fd..4609138dd 100644 --- a/Source/Project64/N64 System/Recompiler/Recompiler Ops.h +++ b/Source/Project64/N64 System/Recompiler/Recompiler Ops.h @@ -191,9 +191,11 @@ protected: static void ExitCodeBlock ( void ); static void CompileReadTLBMiss (int AddressReg, int LookUpReg ); static void CompileWriteTLBMiss (int AddressReg, int LookUpReg ); + static void UpdateSyncCPU (CRegInfo & RegSet, DWORD Cycles); static void UpdateCounters (CRegInfo & RegSet, bool CheckTimer, bool ClearValues = false ); static void CompileSystemCheck ( DWORD TargetPC, CRegInfo RegSet ); static void ChangeDefaultRoundingModel ( void ); + static void OverflowDelaySlot ( void );