Core: Start to handle jump in delay slot
This commit is contained in:
parent
8803f17d85
commit
f380d326fe
|
@ -84,7 +84,7 @@ void CCodeSection::GenerateSectionLinkage()
|
||||||
}
|
}
|
||||||
else if (TargetSection[i] == nullptr && JumpInfo[i]->FallThrough)
|
else if (TargetSection[i] == nullptr && JumpInfo[i]->FallThrough)
|
||||||
{
|
{
|
||||||
m_RecompilerOps->LinkJump(*JumpInfo[i], (uint32_t)-1);
|
m_RecompilerOps->LinkJump(*JumpInfo[i]);
|
||||||
if (JumpInfo[i]->LinkAddress != (uint32_t)-1)
|
if (JumpInfo[i]->LinkAddress != (uint32_t)-1)
|
||||||
{
|
{
|
||||||
JumpInfo[i]->RegSet.UnMap_GPR(31, false);
|
JumpInfo[i]->RegSet.UnMap_GPR(31, false);
|
||||||
|
@ -105,7 +105,7 @@ void CCodeSection::GenerateSectionLinkage()
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
m_RecompilerOps->LinkJump(*JumpInfo[i], (uint32_t)-1);
|
m_RecompilerOps->LinkJump(*JumpInfo[i]);
|
||||||
if (JumpInfo[i]->LinkAddress != (uint32_t)-1)
|
if (JumpInfo[i]->LinkAddress != (uint32_t)-1)
|
||||||
{
|
{
|
||||||
JumpInfo[i]->RegSet.UnMap_GPR(31, false);
|
JumpInfo[i]->RegSet.UnMap_GPR(31, false);
|
||||||
|
@ -151,7 +151,7 @@ void CCodeSection::GenerateSectionLinkage()
|
||||||
if (TargetSection[i]->m_EnterLabel.isValid())
|
if (TargetSection[i]->m_EnterLabel.isValid())
|
||||||
{
|
{
|
||||||
JumpInfo[i]->FallThrough = false;
|
JumpInfo[i]->FallThrough = false;
|
||||||
m_RecompilerOps->LinkJump(*JumpInfo[i], TargetSection[i]->m_SectionID);
|
m_RecompilerOps->LinkJump(*JumpInfo[i]);
|
||||||
if (JumpInfo[i]->LinkAddress != (uint32_t)-1)
|
if (JumpInfo[i]->LinkAddress != (uint32_t)-1)
|
||||||
{
|
{
|
||||||
JumpInfo[i]->RegSet.UnMap_GPR(31, false);
|
JumpInfo[i]->RegSet.UnMap_GPR(31, false);
|
||||||
|
@ -252,7 +252,7 @@ void CCodeSection::GenerateSectionLinkage()
|
||||||
if (TargetSection[i] == nullptr)
|
if (TargetSection[i] == nullptr)
|
||||||
{
|
{
|
||||||
m_CodeBlock.Log("ExitBlock (from %d):", m_SectionID);
|
m_CodeBlock.Log("ExitBlock (from %d):", m_SectionID);
|
||||||
m_RecompilerOps->LinkJump(*JumpInfo[i], (uint32_t)-1);
|
m_RecompilerOps->LinkJump(*JumpInfo[i]);
|
||||||
if (JumpInfo[i]->LinkAddress != (uint32_t)-1)
|
if (JumpInfo[i]->LinkAddress != (uint32_t)-1)
|
||||||
{
|
{
|
||||||
JumpInfo[i]->RegSet.UnMap_GPR(31, false);
|
JumpInfo[i]->RegSet.UnMap_GPR(31, false);
|
||||||
|
@ -276,7 +276,7 @@ void CCodeSection::GenerateSectionLinkage()
|
||||||
stdstr_f Label("Section_%d (from %d):", TargetSection[i]->m_SectionID, m_SectionID);
|
stdstr_f Label("Section_%d (from %d):", TargetSection[i]->m_SectionID, m_SectionID);
|
||||||
|
|
||||||
m_CodeBlock.Log(Label.c_str());
|
m_CodeBlock.Log(Label.c_str());
|
||||||
m_RecompilerOps->LinkJump(*JumpInfo[i], (uint32_t)-1);
|
m_RecompilerOps->LinkJump(*JumpInfo[i]);
|
||||||
if (JumpInfo[i]->LinkAddress != (uint32_t)-1)
|
if (JumpInfo[i]->LinkAddress != (uint32_t)-1)
|
||||||
{
|
{
|
||||||
JumpInfo[i]->RegSet.UnMap_GPR(31, false);
|
JumpInfo[i]->RegSet.UnMap_GPR(31, false);
|
||||||
|
|
|
@ -469,7 +469,44 @@ void CX86RecompilerOps::Compile_BranchCompare(RecompilerBranchCompare CompareTyp
|
||||||
|
|
||||||
void CX86RecompilerOps::Compile_Branch(RecompilerBranchCompare CompareType, bool Link)
|
void CX86RecompilerOps::Compile_Branch(RecompilerBranchCompare CompareType, bool Link)
|
||||||
{
|
{
|
||||||
if (m_PipelineStage == PIPELINE_STAGE_NORMAL)
|
if (m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT)
|
||||||
|
{
|
||||||
|
Compile_BranchCompare(CompareType);
|
||||||
|
if (m_Section->m_Jump.FallThrough || (!m_Section->m_Cont.FallThrough && m_Section->m_Jump.LinkLocation.isValid()))
|
||||||
|
{
|
||||||
|
LinkJump(m_Section->m_Jump);
|
||||||
|
m_Assembler.MoveConstToVariable(&g_System->m_JumpDelayLocation, "System::m_JumpDelayLocation", m_CompilePC + ((int16_t)m_Opcode.offset << 2) + 8);
|
||||||
|
if (m_Section->m_Cont.LinkLocation.isValid())
|
||||||
|
{
|
||||||
|
// jump to link
|
||||||
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_Section->m_Cont.FallThrough)
|
||||||
|
{
|
||||||
|
LinkJump(m_Section->m_Cont);
|
||||||
|
m_Assembler.MoveConstToVariable(&g_System->m_JumpDelayLocation, "System::m_JumpDelayLocation", m_CompilePC + 8);
|
||||||
|
if (m_Section->m_Jump.LinkLocation.isValid())
|
||||||
|
{
|
||||||
|
// jump to link
|
||||||
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_Section->m_Jump.LinkLocation.isValid() || m_Section->m_Cont.LinkLocation.isValid())
|
||||||
|
{
|
||||||
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
if (Link)
|
||||||
|
{
|
||||||
|
Map_GPR_32bit(31, true, -1);
|
||||||
|
m_Assembler.MoveVariableToX86reg(GetMipsRegMapLo(31), &g_System->m_JumpToLocation, "System::m_JumpToLocation");
|
||||||
|
m_Assembler.add(GetMipsRegMapLo(31), 4);
|
||||||
|
}
|
||||||
|
OverflowDelaySlot(false);
|
||||||
|
}
|
||||||
|
else if (m_PipelineStage == PIPELINE_STAGE_NORMAL)
|
||||||
{
|
{
|
||||||
if (CompareType == RecompilerBranchCompare_COP1BCF || CompareType == RecompilerBranchCompare_COP1BCT)
|
if (CompareType == RecompilerBranchCompare_COP1BCF || CompareType == RecompilerBranchCompare_COP1BCT)
|
||||||
{
|
{
|
||||||
|
@ -492,6 +529,11 @@ void CX86RecompilerOps::Compile_Branch(RecompilerBranchCompare CompareType, bool
|
||||||
}
|
}
|
||||||
m_Section->m_Jump.JumpPC = m_CompilePC;
|
m_Section->m_Jump.JumpPC = m_CompilePC;
|
||||||
m_Section->m_Jump.TargetPC = m_CompilePC + ((int16_t)m_Opcode.offset << 2) + 4;
|
m_Section->m_Jump.TargetPC = m_CompilePC + ((int16_t)m_Opcode.offset << 2) + 4;
|
||||||
|
if (m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT)
|
||||||
|
{
|
||||||
|
m_Section->m_Jump.TargetPC += 4;
|
||||||
|
m_EffectDelaySlot = true;
|
||||||
|
}
|
||||||
if (m_Section->m_JumpSection != nullptr)
|
if (m_Section->m_JumpSection != nullptr)
|
||||||
{
|
{
|
||||||
m_Section->m_Jump.BranchLabel = stdstr_f("Section_%d", m_Section->m_JumpSection->m_SectionID);
|
m_Section->m_Jump.BranchLabel = stdstr_f("Section_%d", m_Section->m_JumpSection->m_SectionID);
|
||||||
|
@ -565,15 +607,11 @@ void CX86RecompilerOps::Compile_Branch(RecompilerBranchCompare CompareType, bool
|
||||||
{
|
{
|
||||||
if (m_Section->m_Jump.LinkLocation.isValid())
|
if (m_Section->m_Jump.LinkLocation.isValid())
|
||||||
{
|
{
|
||||||
m_CodeBlock.Log("");
|
|
||||||
m_CodeBlock.Log(" %s:", m_Section->m_Jump.BranchLabel.c_str());
|
|
||||||
LinkJump(m_Section->m_Jump);
|
LinkJump(m_Section->m_Jump);
|
||||||
m_Section->m_Jump.FallThrough = true;
|
m_Section->m_Jump.FallThrough = true;
|
||||||
}
|
}
|
||||||
else if (m_Section->m_Cont.LinkLocation.isValid())
|
else if (m_Section->m_Cont.LinkLocation.isValid())
|
||||||
{
|
{
|
||||||
m_CodeBlock.Log("");
|
|
||||||
m_CodeBlock.Log(" %s:", m_Section->m_Cont.BranchLabel.c_str());
|
|
||||||
LinkJump(m_Section->m_Cont);
|
LinkJump(m_Section->m_Cont);
|
||||||
m_Section->m_Cont.FallThrough = true;
|
m_Section->m_Cont.FallThrough = true;
|
||||||
}
|
}
|
||||||
|
@ -607,8 +645,6 @@ void CX86RecompilerOps::Compile_Branch(RecompilerBranchCompare CompareType, bool
|
||||||
DelayLinkLocation = m_Assembler.newLabel();
|
DelayLinkLocation = m_Assembler.newLabel();
|
||||||
m_Assembler.JmpLabel("DoDelaySlot", DelayLinkLocation);
|
m_Assembler.JmpLabel("DoDelaySlot", DelayLinkLocation);
|
||||||
|
|
||||||
m_CodeBlock.Log(" ");
|
|
||||||
m_CodeBlock.Log(" %s:", m_Section->m_Jump.BranchLabel.c_str());
|
|
||||||
LinkJump(m_Section->m_Jump);
|
LinkJump(m_Section->m_Jump);
|
||||||
m_Assembler.MoveConstToVariable(&g_System->m_JumpToLocation, "System::m_JumpToLocation", m_Section->m_Jump.TargetPC);
|
m_Assembler.MoveConstToVariable(&g_System->m_JumpToLocation, "System::m_JumpToLocation", m_Section->m_Jump.TargetPC);
|
||||||
}
|
}
|
||||||
|
@ -621,8 +657,6 @@ void CX86RecompilerOps::Compile_Branch(RecompilerBranchCompare CompareType, bool
|
||||||
DelayLinkLocation = m_Assembler.newLabel();
|
DelayLinkLocation = m_Assembler.newLabel();
|
||||||
m_Assembler.JmpLabel("DoDelaySlot", DelayLinkLocation);
|
m_Assembler.JmpLabel("DoDelaySlot", DelayLinkLocation);
|
||||||
|
|
||||||
m_CodeBlock.Log(" ");
|
|
||||||
m_CodeBlock.Log(" %s:", m_Section->m_Cont.BranchLabel.c_str());
|
|
||||||
LinkJump(m_Section->m_Cont);
|
LinkJump(m_Section->m_Cont);
|
||||||
m_Assembler.MoveConstToVariable(&g_System->m_JumpToLocation, "System::m_JumpToLocation", m_Section->m_Cont.TargetPC);
|
m_Assembler.MoveConstToVariable(&g_System->m_JumpToLocation, "System::m_JumpToLocation", m_Section->m_Cont.TargetPC);
|
||||||
}
|
}
|
||||||
|
@ -637,8 +671,19 @@ void CX86RecompilerOps::Compile_Branch(RecompilerBranchCompare CompareType, bool
|
||||||
ResetX86Protection();
|
ResetX86Protection();
|
||||||
m_RegBeforeDelay = m_RegWorkingSet;
|
m_RegBeforeDelay = m_RegWorkingSet;
|
||||||
}
|
}
|
||||||
|
if (m_PipelineStage == PIPELINE_STAGE_NORMAL)
|
||||||
|
{
|
||||||
m_PipelineStage = PIPELINE_STAGE_DO_DELAY_SLOT;
|
m_PipelineStage = PIPELINE_STAGE_DO_DELAY_SLOT;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
||||||
|
m_Section->m_Jump.RegSet = m_RegWorkingSet;
|
||||||
|
m_Section->m_Cont.RegSet = m_RegWorkingSet;
|
||||||
|
m_Section->GenerateSectionLinkage();
|
||||||
|
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT_DONE)
|
else if (m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT_DONE)
|
||||||
{
|
{
|
||||||
if (m_CompilePC + ((int16_t)m_Opcode.offset << 2) + 4 == m_CompilePC + 8)
|
if (m_CompilePC + ((int16_t)m_Opcode.offset << 2) + 4 == m_CompilePC + 8)
|
||||||
|
@ -697,7 +742,6 @@ void CX86RecompilerOps::Compile_Branch(RecompilerBranchCompare CompareType, bool
|
||||||
|
|
||||||
if (JumpInfo->LinkLocation.isValid())
|
if (JumpInfo->LinkLocation.isValid())
|
||||||
{
|
{
|
||||||
m_CodeBlock.Log(" %s:", JumpInfo->BranchLabel.c_str());
|
|
||||||
LinkJump(*JumpInfo);
|
LinkJump(*JumpInfo);
|
||||||
JumpInfo->FallThrough = true;
|
JumpInfo->FallThrough = true;
|
||||||
m_PipelineStage = PIPELINE_STAGE_DO_DELAY_SLOT;
|
m_PipelineStage = PIPELINE_STAGE_DO_DELAY_SLOT;
|
||||||
|
@ -2149,6 +2193,14 @@ void CX86RecompilerOps::J()
|
||||||
OverflowDelaySlot(false);
|
OverflowDelaySlot(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
R4300iOpcode DelaySlot;
|
||||||
|
g_MMU->MemoryValue32(m_CompilePC + 4, DelaySlot.Value);
|
||||||
|
if (R4300iInstruction(m_CompilePC + 4, DelaySlot.Value).HasDelaySlot())
|
||||||
|
{
|
||||||
|
m_Assembler.MoveConstToVariable(&g_System->m_JumpToLocation, "System::m_JumpToLocation", (m_CompilePC & 0xF0000000) + (m_Opcode.target << 2));
|
||||||
|
m_PipelineStage = PIPELINE_STAGE_DO_DELAY_SLOT;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_Section->m_Jump.TargetPC = (m_CompilePC & 0xF0000000) + (m_Opcode.target << 2);
|
m_Section->m_Jump.TargetPC = (m_CompilePC & 0xF0000000) + (m_Opcode.target << 2);
|
||||||
m_Section->m_Jump.JumpPC = m_CompilePC;
|
m_Section->m_Jump.JumpPC = m_CompilePC;
|
||||||
|
@ -8644,7 +8696,7 @@ bool CX86RecompilerOps::InheritParentInfo()
|
||||||
CJumpInfo * JumpInfo = m_Section == Parent->m_ContinueSection ? &Parent->m_Cont : &Parent->m_Jump;
|
CJumpInfo * JumpInfo = m_Section == Parent->m_ContinueSection ? &Parent->m_Cont : &Parent->m_Jump;
|
||||||
|
|
||||||
m_Section->m_RegEnter = JumpInfo->RegSet;
|
m_Section->m_RegEnter = JumpInfo->RegSet;
|
||||||
LinkJump(*JumpInfo, m_Section->m_SectionID);
|
LinkJump(*JumpInfo);
|
||||||
SetRegWorkingSet(m_Section->m_RegEnter);
|
SetRegWorkingSet(m_Section->m_RegEnter);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -8734,7 +8786,7 @@ bool CX86RecompilerOps::InheritParentInfo()
|
||||||
|
|
||||||
SetRegWorkingSet(JumpInfo->RegSet);
|
SetRegWorkingSet(JumpInfo->RegSet);
|
||||||
m_RegWorkingSet.ResetX86Protection();
|
m_RegWorkingSet.ResetX86Protection();
|
||||||
LinkJump(*JumpInfo, m_Section->m_SectionID, Parent->m_SectionID);
|
LinkJump(*JumpInfo);
|
||||||
|
|
||||||
if (JumpInfo->Reason == ExitReason_NormalNoSysCheck)
|
if (JumpInfo->Reason == ExitReason_NormalNoSysCheck)
|
||||||
{
|
{
|
||||||
|
@ -9052,10 +9104,11 @@ bool CX86RecompilerOps::InheritParentInfo()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CX86RecompilerOps::LinkJump(CJumpInfo & JumpInfo, uint32_t SectionID, uint32_t FromSectionID)
|
void CX86RecompilerOps::LinkJump(CJumpInfo & JumpInfo)
|
||||||
{
|
{
|
||||||
if (JumpInfo.LinkLocation.isValid())
|
if (JumpInfo.LinkLocation.isValid())
|
||||||
{
|
{
|
||||||
|
m_CodeBlock.Log("");
|
||||||
m_Assembler.bind(JumpInfo.LinkLocation);
|
m_Assembler.bind(JumpInfo.LinkLocation);
|
||||||
JumpInfo.LinkLocation = asmjit::Label();
|
JumpInfo.LinkLocation = asmjit::Label();
|
||||||
if (JumpInfo.LinkLocation2.isValid())
|
if (JumpInfo.LinkLocation2.isValid())
|
||||||
|
@ -9235,15 +9288,24 @@ void CX86RecompilerOps::OverflowDelaySlot(bool TestTimer)
|
||||||
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
||||||
m_RegWorkingSet.WriteBackRegisters();
|
m_RegWorkingSet.WriteBackRegisters();
|
||||||
UpdateCounters(m_RegWorkingSet, false, true);
|
UpdateCounters(m_RegWorkingSet, false, true);
|
||||||
|
if (m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT)
|
||||||
|
{
|
||||||
|
m_Assembler.MoveVariableToX86reg(asmjit::x86::ecx, &g_System->m_JumpToLocation, "System::m_JumpToLocation");
|
||||||
|
m_Assembler.MoveX86regToVariable(_PROGRAM_COUNTER, "PROGRAM_COUNTER", asmjit::x86::ecx);
|
||||||
|
m_Assembler.MoveVariableToX86reg(asmjit::x86::ecx, &g_System->m_JumpDelayLocation, "System::JumpDelayLocation");
|
||||||
|
m_Assembler.MoveX86regToVariable(&g_System->m_JumpToLocation, "System::m_JumpToLocation", asmjit::x86::ecx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
m_Assembler.MoveConstToVariable(_PROGRAM_COUNTER, "PROGRAM_COUNTER", CompilePC() + 4);
|
m_Assembler.MoveConstToVariable(_PROGRAM_COUNTER, "PROGRAM_COUNTER", CompilePC() + 4);
|
||||||
|
}
|
||||||
if (g_SyncSystem)
|
if (g_SyncSystem)
|
||||||
{
|
{
|
||||||
m_Assembler.CallThis((uint32_t)g_BaseSystem, AddressOf(&CN64System::SyncSystem), "CN64System::SyncSystem", 4);
|
m_Assembler.CallThis((uint32_t)g_BaseSystem, AddressOf(&CN64System::SyncSystem), "CN64System::SyncSystem", 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", PIPELINE_STAGE_JUMP);
|
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", PIPELINE_STAGE_JUMP);
|
||||||
|
|
||||||
|
|
||||||
if (TestTimer)
|
if (TestTimer)
|
||||||
{
|
{
|
||||||
m_Assembler.MoveConstToVariable(&R4300iOp::m_TestTimer, "R4300iOp::m_TestTimer", TestTimer);
|
m_Assembler.MoveConstToVariable(&R4300iOp::m_TestTimer, "R4300iOp::m_TestTimer", TestTimer);
|
||||||
|
|
|
@ -224,7 +224,7 @@ public:
|
||||||
CRegInfo & GetRegWorkingSet(void);
|
CRegInfo & GetRegWorkingSet(void);
|
||||||
void SetRegWorkingSet(const CRegInfo & RegInfo);
|
void SetRegWorkingSet(const CRegInfo & RegInfo);
|
||||||
bool InheritParentInfo();
|
bool InheritParentInfo();
|
||||||
void LinkJump(CJumpInfo & JumpInfo, uint32_t SectionID = -1, uint32_t FromSectionID = -1);
|
void LinkJump(CJumpInfo & JumpInfo);
|
||||||
void JumpToSection(CCodeSection * Section);
|
void JumpToSection(CCodeSection * Section);
|
||||||
void JumpToUnknown(CJumpInfo * JumpInfo);
|
void JumpToUnknown(CJumpInfo * JumpInfo);
|
||||||
void SetCurrentPC(uint32_t ProgramCounter);
|
void SetCurrentPC(uint32_t ProgramCounter);
|
||||||
|
|
Loading…
Reference in New Issue