2012-12-19 09:30:18 +00:00
|
|
|
/****************************************************************************
|
|
|
|
* *
|
2015-11-10 05:21:49 +00:00
|
|
|
* Project64 - A Nintendo 64 emulator. *
|
2012-12-19 09:30:18 +00:00
|
|
|
* http://www.pj64-emu.com/ *
|
|
|
|
* Copyright (C) 2012 Project64. All rights reserved. *
|
|
|
|
* *
|
|
|
|
* License: *
|
|
|
|
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
|
|
|
* *
|
|
|
|
****************************************************************************/
|
2010-05-30 01:54:42 +00:00
|
|
|
#include "stdafx.h"
|
2016-01-13 11:15:30 +00:00
|
|
|
#include <Project64-core/N64System/Recompiler/CodeSection.h>
|
2015-12-06 09:59:58 +00:00
|
|
|
#include <Project64-core/N64System/Mips/OpCode.h>
|
|
|
|
#include <Project64-core/N64System/SystemGlobals.h>
|
2015-12-21 07:35:22 +00:00
|
|
|
#include <Project64-core/N64System/Mips/MemoryVirtualMem.h>
|
2016-06-27 07:26:35 +00:00
|
|
|
#include <Project64-core/N64System/Recompiler/RecompilerCodeLog.h>
|
2015-12-06 09:59:58 +00:00
|
|
|
#include <Project64-core/N64System/Recompiler/CodeBlock.h>
|
|
|
|
#include <Project64-core/N64System/N64Class.h>
|
|
|
|
#include <Project64-core/N64System/Interpreter/InterpreterCPU.h>
|
|
|
|
#include <Project64-core/N64System/Recompiler/LoopAnalysis.h>
|
|
|
|
#include <Project64-core/N64System/Recompiler/SectionInfo.h>
|
2016-01-13 11:15:30 +00:00
|
|
|
#include <Project64-core/ExceptionHandler.h>
|
2010-05-30 01:54:42 +00:00
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void InPermLoop();
|
2010-05-30 01:54:42 +00:00
|
|
|
|
2015-11-08 20:55:32 +00:00
|
|
|
bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2);
|
2010-05-30 01:54:42 +00:00
|
|
|
|
2015-11-09 06:55:16 +00:00
|
|
|
static bool DelaySlotEffectsJump(uint32_t JumpPC)
|
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
OPCODE Command;
|
|
|
|
|
|
|
|
if (!g_MMU->LW_VAddr(JumpPC, Command.Hex))
|
2016-01-18 11:04:49 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
return true;
|
2016-01-18 11:04:49 +00:00
|
|
|
}
|
2015-11-15 02:27:06 +00:00
|
|
|
|
|
|
|
switch (Command.op)
|
|
|
|
{
|
|
|
|
case R4300i_SPECIAL:
|
|
|
|
switch (Command.funct)
|
|
|
|
{
|
|
|
|
case R4300i_SPECIAL_JR: return DelaySlotEffectsCompare(JumpPC, Command.rs, 0);
|
|
|
|
case R4300i_SPECIAL_JALR: return DelaySlotEffectsCompare(JumpPC, Command.rs, 31);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R4300i_REGIMM:
|
|
|
|
switch (Command.rt)
|
|
|
|
{
|
|
|
|
case R4300i_REGIMM_BLTZ:
|
|
|
|
case R4300i_REGIMM_BGEZ:
|
|
|
|
case R4300i_REGIMM_BLTZL:
|
|
|
|
case R4300i_REGIMM_BGEZL:
|
|
|
|
case R4300i_REGIMM_BLTZAL:
|
|
|
|
case R4300i_REGIMM_BGEZAL:
|
|
|
|
return DelaySlotEffectsCompare(JumpPC, Command.rs, 0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R4300i_JAL:
|
|
|
|
case R4300i_SPECIAL_JALR: return DelaySlotEffectsCompare(JumpPC, 31, 0); break;
|
|
|
|
case R4300i_J: return false;
|
|
|
|
case R4300i_BEQ:
|
|
|
|
case R4300i_BNE:
|
|
|
|
case R4300i_BLEZ:
|
|
|
|
case R4300i_BGTZ:
|
|
|
|
return DelaySlotEffectsCompare(JumpPC, Command.rs, Command.rt);
|
|
|
|
case R4300i_CP1:
|
|
|
|
switch (Command.fmt)
|
|
|
|
{
|
|
|
|
case R4300i_COP1_BC:
|
|
|
|
switch (Command.ft)
|
|
|
|
{
|
|
|
|
case R4300i_COP1_BC_BCF:
|
|
|
|
case R4300i_COP1_BC_BCT:
|
|
|
|
case R4300i_COP1_BC_BCFL:
|
|
|
|
case R4300i_COP1_BC_BCTL:
|
|
|
|
{
|
2016-01-18 11:04:49 +00:00
|
|
|
bool EffectDelaySlot = false;
|
|
|
|
OPCODE NewCommand;
|
2015-11-15 02:27:06 +00:00
|
|
|
|
2016-01-18 11:04:49 +00:00
|
|
|
if (!g_MMU->LW_VAddr(JumpPC + 4, NewCommand.Hex))
|
2015-11-15 02:27:06 +00:00
|
|
|
{
|
2016-01-18 11:04:49 +00:00
|
|
|
return true;
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
2016-01-18 11:04:49 +00:00
|
|
|
|
|
|
|
if (NewCommand.op == R4300i_CP1)
|
2015-11-15 02:27:06 +00:00
|
|
|
{
|
2016-01-18 11:04:49 +00:00
|
|
|
if (NewCommand.fmt == R4300i_COP1_S && (NewCommand.funct & 0x30) == 0x30)
|
|
|
|
{
|
|
|
|
EffectDelaySlot = true;
|
|
|
|
}
|
|
|
|
if (NewCommand.fmt == R4300i_COP1_D && (NewCommand.funct & 0x30) == 0x30)
|
|
|
|
{
|
|
|
|
EffectDelaySlot = true;
|
|
|
|
}
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
2016-01-18 11:04:49 +00:00
|
|
|
return EffectDelaySlot;
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
2016-01-18 11:04:49 +00:00
|
|
|
break;
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R4300i_BEQL:
|
|
|
|
case R4300i_BNEL:
|
|
|
|
case R4300i_BLEZL:
|
|
|
|
case R4300i_BGTZL:
|
|
|
|
return DelaySlotEffectsCompare(JumpPC, Command.rs, Command.rt);
|
|
|
|
}
|
|
|
|
return true;
|
2010-05-30 01:54:42 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 06:55:16 +00:00
|
|
|
CCodeSection::CCodeSection(CCodeBlock * CodeBlock, uint32_t EnterPC, uint32_t ID, bool LinkAllowed) :
|
2016-01-18 11:04:49 +00:00
|
|
|
m_BlockInfo(CodeBlock),
|
|
|
|
m_SectionID(ID),
|
|
|
|
m_EnterPC(EnterPC),
|
|
|
|
m_EndPC((uint32_t)-1),
|
|
|
|
m_ContinueSection(NULL),
|
|
|
|
m_JumpSection(NULL),
|
|
|
|
m_EndSection(false),
|
|
|
|
m_LinkAllowed(LinkAllowed),
|
|
|
|
m_Test(0),
|
|
|
|
m_Test2(0),
|
|
|
|
m_CompiledLocation(NULL),
|
|
|
|
m_InLoop(false),
|
|
|
|
m_DelaySlot(false)
|
2010-05-30 01:54:42 +00:00
|
|
|
{
|
2016-01-18 11:04:49 +00:00
|
|
|
CPU_Message("%s: ID %d EnterPC 0x%08X", __FUNCTION__, ID, EnterPC);
|
2010-05-30 01:54:42 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
CCodeSection::~CCodeSection()
|
2010-05-30 01:54:42 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CCodeSection::GenerateSectionLinkage()
|
2010-05-30 01:54:42 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
CCodeSection * TargetSection[] = { m_ContinueSection, m_JumpSection };
|
|
|
|
CJumpInfo * JumpInfo[] = { &m_Cont, &m_Jump };
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if (JumpInfo[i]->LinkLocation == NULL &&
|
|
|
|
JumpInfo[i]->FallThrough == false)
|
|
|
|
{
|
|
|
|
JumpInfo[i]->TargetPC = (uint32_t)-1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((CompilePC() & 0xFFC) == 0xFFC)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-12-15 06:01:06 +00:00
|
|
|
#ifdef legacycode
|
2015-11-15 02:27:06 +00:00
|
|
|
//Handle Fall througth
|
|
|
|
uint8_t * Jump = NULL;
|
|
|
|
for (i = 0; i < 2; i ++)
|
|
|
|
{
|
|
|
|
if (!JumpInfo[i]->FallThrough) { continue; }
|
|
|
|
JumpInfo[i]->FallThrough = false;
|
|
|
|
if (JumpInfo[i]->LinkLocation != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo[i]->LinkLocation,(uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo[i]->LinkLocation = NULL;
|
|
|
|
if (JumpInfo[i]->LinkLocation2 != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo[i]->LinkLocation2,(uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo[i]->LinkLocation2 = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PushImm32(stdstr_f("0x%08X",JumpInfo[i]->TargetPC).c_str(),JumpInfo[i]->TargetPC);
|
|
|
|
if (JumpInfo[(i + 1) & 1]->LinkLocation == NULL) { break; }
|
|
|
|
JmpLabel8("FinishBlock",0);
|
2016-06-28 11:22:30 +00:00
|
|
|
Jump = *g_RecompPos - 1;
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
for (i = 0; i < 2; i ++)
|
|
|
|
{
|
|
|
|
if (JumpInfo[i]->LinkLocation == NULL) { continue; }
|
|
|
|
JumpInfo[i]->FallThrough = false;
|
|
|
|
if (JumpInfo[i]->LinkLocation != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo[i]->LinkLocation,(uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo[i]->LinkLocation = NULL;
|
|
|
|
if (JumpInfo[i]->LinkLocation2 != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo[i]->LinkLocation2,(uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo[i]->LinkLocation2 = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PushImm32(stdstr_f("0x%08X",JumpInfo[i]->TargetPC).c_str(),JumpInfo[i]->TargetPC);
|
|
|
|
if (JumpInfo[(i + 1) & 1]->LinkLocation == NULL) { break; }
|
|
|
|
JmpLabel8("FinishBlock",0);
|
2016-06-28 11:22:30 +00:00
|
|
|
Jump = *g_RecompPos - 1;
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
if (Jump != NULL)
|
|
|
|
{
|
|
|
|
CPU_Message(" $FinishBlock:");
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump8(Jump,*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
//MoveConstToVariable(CompilePC() + 4,_PROGRAM_COUNTER,"PROGRAM_COUNTER");
|
|
|
|
m_RegWorkingSet.WriteBackRegisters();
|
|
|
|
UpdateCounters(m_RegWorkingSet,false,true);
|
|
|
|
// WriteBackRegisters(Section);
|
|
|
|
// if (g_SyncSystem) {
|
|
|
|
MoveConstToX86reg((uint32_t)g_BaseSystem,x86_ECX);
|
|
|
|
Call_Direct(AddressOf(&CN64System::SyncSystem), "CN64System::SyncSystem");
|
2015-11-15 03:27:59 +00:00
|
|
|
//}
|
2015-11-15 02:27:06 +00:00
|
|
|
// MoveConstToVariable(DELAY_SLOT,&m_NextInstruction,"m_NextInstruction");
|
|
|
|
PushImm32(stdstr_f("0x%08X",CompilePC() + 4).c_str(),CompilePC() + 4);
|
|
|
|
|
|
|
|
// check if there is an existing section
|
|
|
|
|
|
|
|
MoveConstToX86reg((uint32_t)g_Recompiler,x86_ECX);
|
|
|
|
Call_Direct(AddressOf(&CRecompiler::CompileDelaySlot), "CRecompiler::CompileDelaySlot");
|
|
|
|
JmpDirectReg(x86_EAX);
|
|
|
|
ExitCodeBlock();
|
|
|
|
return;
|
2012-09-25 05:58:06 +00:00
|
|
|
#endif
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Handle Perm Loop
|
|
|
|
if (CRecompilerOps::m_CompilePC == m_Jump.TargetPC && (m_Cont.FallThrough == false))
|
|
|
|
{
|
|
|
|
if (!DelaySlotEffectsJump(CompilePC()))
|
|
|
|
{
|
|
|
|
MoveConstToVariable(CompilePC(), _PROGRAM_COUNTER, "PROGRAM_COUNTER");
|
|
|
|
m_Jump.RegSet.WriteBackRegisters();
|
|
|
|
UpdateCounters(m_Jump.RegSet, false, true);
|
|
|
|
Call_Direct(AddressOf(CInterpreterCPU::InPermLoop), "CInterpreterCPU::InPermLoop");
|
|
|
|
MoveConstToX86reg((uint32_t)g_SystemTimer, x86_ECX);
|
|
|
|
Call_Direct(AddressOf(&CSystemTimer::TimerDone), "CSystemTimer::TimerDone");
|
|
|
|
CPU_Message("CompileSystemCheck 3");
|
|
|
|
CompileSystemCheck((uint32_t)-1, m_Jump.RegSet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (TargetSection[0] != TargetSection[1] || TargetSection[0] == NULL)
|
|
|
|
{
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if (JumpInfo[i]->LinkLocation == NULL && JumpInfo[i]->FallThrough == false)
|
|
|
|
{
|
|
|
|
if (TargetSection[i])
|
|
|
|
{
|
|
|
|
TargetSection[i]->UnlinkParent(this, i == 0);
|
|
|
|
TargetSection[i] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (TargetSection[i] == NULL && JumpInfo[i]->FallThrough)
|
|
|
|
{
|
|
|
|
if (JumpInfo[i]->LinkLocation != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo[i]->LinkLocation, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo[i]->LinkLocation = NULL;
|
|
|
|
if (JumpInfo[i]->LinkLocation2 != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo[i]->LinkLocation2, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo[i]->LinkLocation2 = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CompileExit(JumpInfo[i]->JumpPC, JumpInfo[i]->TargetPC, JumpInfo[i]->RegSet, JumpInfo[i]->ExitReason, true, NULL);
|
|
|
|
JumpInfo[i]->FallThrough = false;
|
|
|
|
}
|
|
|
|
else if (TargetSection[i] != NULL && JumpInfo[i] != NULL)
|
|
|
|
{
|
|
|
|
if (!JumpInfo[i]->FallThrough) { continue; }
|
|
|
|
if (JumpInfo[i]->TargetPC == TargetSection[i]->m_EnterPC) { continue; }
|
|
|
|
if (JumpInfo[i]->LinkLocation != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo[i]->LinkLocation, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo[i]->LinkLocation = NULL;
|
|
|
|
if (JumpInfo[i]->LinkLocation2 != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo[i]->LinkLocation2, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo[i]->LinkLocation2 = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CompileExit(JumpInfo[i]->JumpPC, JumpInfo[i]->TargetPC, JumpInfo[i]->RegSet, JumpInfo[i]->ExitReason, true, NULL);
|
|
|
|
//FreeSection(TargetSection[i],Section);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_Cont.LinkLocation == NULL && m_Cont.FallThrough == false) { m_ContinueSection = NULL; }
|
|
|
|
if (m_Jump.LinkLocation == NULL && m_Jump.FallThrough == false) { m_JumpSection = NULL; }
|
|
|
|
if (m_JumpSection == NULL && m_ContinueSection == NULL)
|
|
|
|
{
|
|
|
|
//FreeSection(TargetSection[0],Section);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TargetSection[0] = m_ContinueSection;
|
|
|
|
TargetSection[1] = m_JumpSection;
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
if (TargetSection[i] == NULL) { continue; }
|
|
|
|
if (!JumpInfo[i]->FallThrough) { continue; }
|
|
|
|
|
|
|
|
if (TargetSection[i]->m_CompiledLocation != NULL)
|
|
|
|
{
|
|
|
|
char Label[100];
|
|
|
|
sprintf(Label, "Section_%d", TargetSection[i]->m_SectionID);
|
|
|
|
JumpInfo[i]->FallThrough = false;
|
|
|
|
if (JumpInfo[i]->LinkLocation != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo[i]->LinkLocation, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo[i]->LinkLocation = NULL;
|
|
|
|
if (JumpInfo[i]->LinkLocation2 != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo[i]->LinkLocation2, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo[i]->LinkLocation2 = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (JumpInfo[i]->TargetPC <= CompilePC())
|
|
|
|
{
|
|
|
|
if (JumpInfo[i]->PermLoop)
|
|
|
|
{
|
|
|
|
CPU_Message("PermLoop *** 1");
|
|
|
|
MoveConstToVariable(JumpInfo[i]->TargetPC, _PROGRAM_COUNTER, "PROGRAM_COUNTER");
|
|
|
|
UpdateCounters(JumpInfo[i]->RegSet, false, true);
|
|
|
|
if (g_SyncSystem)
|
|
|
|
{
|
|
|
|
MoveConstToX86reg((uint32_t)g_BaseSystem, x86_ECX);
|
|
|
|
Call_Direct(AddressOf(&CN64System::SyncSystem), "CN64System::SyncSystem");
|
|
|
|
}
|
|
|
|
|
|
|
|
//JumpInfo[i]->RegSet.BlockCycleCount() -= g_System->CountPerOp();
|
|
|
|
Call_Direct(AddressOf(CInterpreterCPU::InPermLoop), "CInterpreterCPU::InPermLoop");
|
|
|
|
//JumpInfo[i]->RegSet.BlockCycleCount() += g_System->CountPerOp();
|
|
|
|
UpdateCounters(JumpInfo[i]->RegSet, true, true);
|
|
|
|
CPU_Message("CompileSystemCheck 4");
|
|
|
|
CompileSystemCheck((uint32_t)-1, JumpInfo[i]->RegSet);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UpdateCounters(JumpInfo[i]->RegSet, true, true);
|
|
|
|
CPU_Message("CompileSystemCheck 5");
|
|
|
|
CompileSystemCheck(JumpInfo[i]->TargetPC, JumpInfo[i]->RegSet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UpdateCounters(JumpInfo[i]->RegSet, false, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
JumpInfo[i]->RegSet.SetBlockCycleCount(0);
|
|
|
|
m_RegWorkingSet = JumpInfo[i]->RegSet;
|
|
|
|
SyncRegState(TargetSection[i]->m_RegEnter);
|
|
|
|
JmpLabel32(Label, 0);
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32((uint32_t *)*g_RecompPos - 1, (uint32_t *)(TargetSection[i]->m_CompiledLocation));
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if (TargetSection[i] == NULL) { continue; }
|
|
|
|
if (TargetSection[i]->m_ParentSection.empty()) { continue; }
|
|
|
|
for (SECTION_LIST::iterator iter = TargetSection[i]->m_ParentSection.begin(); iter != TargetSection[i]->m_ParentSection.end(); iter++)
|
|
|
|
{
|
|
|
|
CCodeSection * Parent = *iter;
|
|
|
|
|
|
|
|
if (Parent->m_CompiledLocation != NULL) { continue; }
|
|
|
|
if (Parent->m_InLoop) { continue; }
|
|
|
|
if (JumpInfo[i]->PermLoop)
|
|
|
|
{
|
|
|
|
CPU_Message("PermLoop *** 2");
|
|
|
|
MoveConstToVariable(JumpInfo[i]->TargetPC, _PROGRAM_COUNTER, "PROGRAM_COUNTER");
|
|
|
|
UpdateCounters(JumpInfo[i]->RegSet, false, true);
|
|
|
|
Call_Direct(AddressOf(CInterpreterCPU::InPermLoop), "CInterpreterCPU::InPermLoop");
|
|
|
|
UpdateCounters(JumpInfo[i]->RegSet, true, true);
|
|
|
|
CPU_Message("CompileSystemCheck 6");
|
|
|
|
CompileSystemCheck((uint32_t)-1, JumpInfo[i]->RegSet);
|
|
|
|
}
|
|
|
|
if (JumpInfo[i]->FallThrough)
|
|
|
|
{
|
|
|
|
JumpInfo[i]->FallThrough = false;
|
|
|
|
JmpLabel32(JumpInfo[i]->BranchLabel.c_str(), 0);
|
2016-06-28 11:22:30 +00:00
|
|
|
JumpInfo[i]->LinkLocation = (uint32_t*)(*g_RecompPos - 4);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if (JumpInfo[i]->FallThrough)
|
|
|
|
{
|
|
|
|
if (JumpInfo[i]->TargetPC < CompilePC())
|
|
|
|
{
|
|
|
|
UpdateCounters(JumpInfo[i]->RegSet, true, true);
|
|
|
|
CPU_Message("CompileSystemCheck 7");
|
|
|
|
CompileSystemCheck(JumpInfo[i]->TargetPC, JumpInfo[i]->RegSet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CPU_Message("====== End of Section %d ======", m_SectionID);
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
2016-06-27 11:49:15 +00:00
|
|
|
if (JumpInfo[i]->FallThrough && !TargetSection[i]->GenerateNativeCode(m_BlockInfo->NextTest()))
|
2015-11-15 02:27:06 +00:00
|
|
|
{
|
|
|
|
JumpInfo[i]->FallThrough = false;
|
|
|
|
JmpLabel32(JumpInfo[i]->BranchLabel.c_str(), 0);
|
2016-06-28 11:22:30 +00:00
|
|
|
JumpInfo[i]->LinkLocation = (uint32_t *)(*g_RecompPos - 4);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//CPU_Message("Section %d",m_SectionID);
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if (JumpInfo[i]->LinkLocation == NULL) { continue; }
|
|
|
|
if (TargetSection[i] == NULL)
|
|
|
|
{
|
|
|
|
CPU_Message("ExitBlock (from %d):", m_SectionID);
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo[i]->LinkLocation, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo[i]->LinkLocation = NULL;
|
|
|
|
if (JumpInfo[i]->LinkLocation2 != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo[i]->LinkLocation2, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo[i]->LinkLocation2 = NULL;
|
|
|
|
}
|
|
|
|
CompileExit(JumpInfo[i]->JumpPC, JumpInfo[i]->TargetPC, JumpInfo[i]->RegSet, JumpInfo[i]->ExitReason, true, NULL);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (JumpInfo[i]->TargetPC != TargetSection[i]->m_EnterPC)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
if (TargetSection[i]->m_CompiledLocation == NULL)
|
|
|
|
{
|
2016-06-27 11:49:15 +00:00
|
|
|
TargetSection[i]->GenerateNativeCode(m_BlockInfo->NextTest());
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
stdstr_f Label("Section_%d (from %d):", TargetSection[i]->m_SectionID, m_SectionID);
|
|
|
|
|
|
|
|
CPU_Message(Label.c_str());
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo[i]->LinkLocation, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo[i]->LinkLocation = NULL;
|
|
|
|
if (JumpInfo[i]->LinkLocation2 != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo[i]->LinkLocation2, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo[i]->LinkLocation2 = NULL;
|
|
|
|
}
|
|
|
|
m_RegWorkingSet = JumpInfo[i]->RegSet;
|
|
|
|
if (JumpInfo[i]->TargetPC <= JumpInfo[i]->JumpPC)
|
|
|
|
{
|
|
|
|
UpdateCounters(JumpInfo[i]->RegSet, true, true);
|
|
|
|
if (JumpInfo[i]->PermLoop)
|
|
|
|
{
|
|
|
|
CPU_Message("PermLoop *** 3");
|
|
|
|
MoveConstToVariable(JumpInfo[i]->TargetPC, _PROGRAM_COUNTER, "PROGRAM_COUNTER");
|
|
|
|
Call_Direct(AddressOf(CInterpreterCPU::InPermLoop), "CInterpreterCPU::InPermLoop");
|
|
|
|
CPU_Message("CompileSystemCheck 8");
|
|
|
|
CompileSystemCheck((uint32_t)-1, JumpInfo[i]->RegSet);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CPU_Message("CompileSystemCheck 9");
|
|
|
|
CompileSystemCheck(JumpInfo[i]->TargetPC, JumpInfo[i]->RegSet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
|
|
}
|
|
|
|
m_RegWorkingSet = JumpInfo[i]->RegSet;
|
|
|
|
SyncRegState(TargetSection[i]->m_RegEnter);
|
|
|
|
JmpLabel32(Label.c_str(), 0);
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32((uint32_t *)*g_RecompPos - 1, (uint32_t *)(TargetSection[i]->m_CompiledLocation));
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
}
|
2010-05-30 01:54:42 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 06:55:16 +00:00
|
|
|
void CCodeSection::SyncRegState(const CRegInfo & SyncTo)
|
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
ResetX86Protection();
|
|
|
|
|
|
|
|
bool changed = false;
|
|
|
|
UnMap_AllFPRs();
|
|
|
|
if (m_RegWorkingSet.GetRoundingModel() != SyncTo.GetRoundingModel()) { m_RegWorkingSet.SetRoundingModel(CRegInfo::RoundUnknown); }
|
|
|
|
x86Reg MemStackReg = Get_MemoryStack();
|
|
|
|
x86Reg TargetStackReg = SyncTo.Get_MemoryStack();
|
|
|
|
|
|
|
|
//CPU_Message("MemoryStack for Original State = %s",MemStackReg > 0?x86_Name(MemStackReg):"Not Mapped");
|
|
|
|
if (MemStackReg != TargetStackReg)
|
|
|
|
{
|
|
|
|
if (TargetStackReg == x86_Unknown)
|
|
|
|
{
|
|
|
|
UnMap_X86reg(MemStackReg);
|
|
|
|
}
|
|
|
|
else if (MemStackReg == x86_Unknown)
|
|
|
|
{
|
|
|
|
UnMap_X86reg(TargetStackReg);
|
|
|
|
CPU_Message(" regcache: allocate %s as Memory Stack", x86_Name(TargetStackReg));
|
|
|
|
m_RegWorkingSet.SetX86Mapped(TargetStackReg, CRegInfo::Stack_Mapped);
|
|
|
|
MoveVariableToX86reg(&g_Recompiler->MemoryStackPos(), "MemoryStack", TargetStackReg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UnMap_X86reg(TargetStackReg);
|
|
|
|
CPU_Message(" regcache: change allocation of Memory Stack from %s to %s", x86_Name(MemStackReg), x86_Name(TargetStackReg));
|
|
|
|
m_RegWorkingSet.SetX86Mapped(TargetStackReg, CRegInfo::Stack_Mapped);
|
|
|
|
m_RegWorkingSet.SetX86Mapped(MemStackReg, CRegInfo::NotMapped);
|
|
|
|
MoveX86RegToX86Reg(MemStackReg, TargetStackReg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 1; i < 32; i++)
|
|
|
|
{
|
|
|
|
if (GetMipsRegState(i) == SyncTo.GetMipsRegState(i) ||
|
|
|
|
(g_System->b32BitCore() && GetMipsRegState(i) == CRegInfo::STATE_MAPPED_32_ZERO && SyncTo.GetMipsRegState(i) == CRegInfo::STATE_MAPPED_32_SIGN) ||
|
|
|
|
(g_System->b32BitCore() && GetMipsRegState(i) == CRegInfo::STATE_MAPPED_32_SIGN && SyncTo.GetMipsRegState(i) == CRegInfo::STATE_MAPPED_32_ZERO))
|
|
|
|
{
|
|
|
|
switch (GetMipsRegState(i)) {
|
|
|
|
case CRegInfo::STATE_UNKNOWN: continue;
|
|
|
|
case CRegInfo::STATE_MAPPED_64:
|
|
|
|
if (GetMipsRegMapHi(i) == SyncTo.GetMipsRegMapHi(i) &&
|
|
|
|
GetMipsRegMapLo(i) == SyncTo.GetMipsRegMapLo(i))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_MAPPED_32_ZERO:
|
|
|
|
case CRegInfo::STATE_MAPPED_32_SIGN:
|
|
|
|
if (GetMipsRegMapLo(i) == SyncTo.GetMipsRegMapLo(i))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_CONST_64:
|
|
|
|
if (GetMipsReg(i) != SyncTo.GetMipsReg(i))
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
case CRegInfo::STATE_CONST_32_SIGN:
|
|
|
|
if (GetMipsRegLo(i) != SyncTo.GetMipsRegLo(i))
|
|
|
|
{
|
|
|
|
CPU_Message("Value of const is different Reg %d (%s) Value: 0x%08X to 0x%08X", i, CRegName::GPR[i], GetMipsRegLo(i), SyncTo.GetMipsRegLo(i));
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
CPU_Message("Unhandled Reg state %d\nin SyncRegState", GetMipsRegState(i));
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
changed = true;
|
|
|
|
|
|
|
|
switch (SyncTo.GetMipsRegState(i))
|
|
|
|
{
|
|
|
|
case CRegInfo::STATE_UNKNOWN: UnMap_GPR(i, true); break;
|
|
|
|
case CRegInfo::STATE_MAPPED_64:
|
|
|
|
{
|
2016-01-18 11:04:49 +00:00
|
|
|
x86Reg Reg = SyncTo.GetMipsRegMapLo(i);
|
|
|
|
x86Reg x86RegHi = SyncTo.GetMipsRegMapHi(i);
|
|
|
|
UnMap_X86reg(Reg);
|
|
|
|
UnMap_X86reg(x86RegHi);
|
|
|
|
switch (GetMipsRegState(i))
|
|
|
|
{
|
|
|
|
case CRegInfo::STATE_UNKNOWN:
|
|
|
|
MoveVariableToX86reg(&_GPR[i].UW[0], CRegName::GPR_Lo[i], Reg);
|
|
|
|
MoveVariableToX86reg(&_GPR[i].UW[1], CRegName::GPR_Hi[i], x86RegHi);
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_MAPPED_64:
|
|
|
|
MoveX86RegToX86Reg(GetMipsRegMapLo(i), Reg);
|
|
|
|
m_RegWorkingSet.SetX86Mapped(GetMipsRegMapLo(i), CRegInfo::NotMapped);
|
|
|
|
MoveX86RegToX86Reg(GetMipsRegMapHi(i), x86RegHi);
|
|
|
|
m_RegWorkingSet.SetX86Mapped(GetMipsRegMapHi(i), CRegInfo::NotMapped);
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_MAPPED_32_SIGN:
|
|
|
|
MoveX86RegToX86Reg(GetMipsRegMapLo(i), x86RegHi);
|
|
|
|
ShiftRightSignImmed(x86RegHi, 31);
|
|
|
|
MoveX86RegToX86Reg(GetMipsRegMapLo(i), Reg);
|
|
|
|
m_RegWorkingSet.SetX86Mapped(GetMipsRegMapLo(i), CRegInfo::NotMapped);
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_MAPPED_32_ZERO:
|
|
|
|
XorX86RegToX86Reg(x86RegHi, x86RegHi);
|
|
|
|
MoveX86RegToX86Reg(GetMipsRegMapLo(i), Reg);
|
|
|
|
m_RegWorkingSet.SetX86Mapped(GetMipsRegMapLo(i), CRegInfo::NotMapped);
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_CONST_64:
|
|
|
|
MoveConstToX86reg(GetMipsRegHi(i), x86RegHi);
|
|
|
|
MoveConstToX86reg(GetMipsRegLo(i), Reg);
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_CONST_32_SIGN:
|
|
|
|
MoveConstToX86reg(GetMipsRegLo_S(i) >> 31, x86RegHi);
|
|
|
|
MoveConstToX86reg(GetMipsRegLo(i), Reg);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
CPU_Message("Do something with states in SyncRegState\nSTATE_MAPPED_64\n%d", GetMipsRegState(i));
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
m_RegWorkingSet.SetMipsRegMapLo(i, Reg);
|
|
|
|
m_RegWorkingSet.SetMipsRegMapHi(i, x86RegHi);
|
|
|
|
m_RegWorkingSet.SetMipsRegState(i, CRegInfo::STATE_MAPPED_64);
|
|
|
|
m_RegWorkingSet.SetX86Mapped(Reg, CRegInfo::GPR_Mapped);
|
|
|
|
m_RegWorkingSet.SetX86Mapped(x86RegHi, CRegInfo::GPR_Mapped);
|
|
|
|
m_RegWorkingSet.SetX86MapOrder(Reg, 1);
|
|
|
|
m_RegWorkingSet.SetX86MapOrder(x86RegHi, 1);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
2016-01-18 11:04:49 +00:00
|
|
|
break;
|
2015-11-15 02:27:06 +00:00
|
|
|
case CRegInfo::STATE_MAPPED_32_SIGN:
|
|
|
|
{
|
2016-01-18 11:04:49 +00:00
|
|
|
x86Reg Reg = SyncTo.GetMipsRegMapLo(i);
|
|
|
|
UnMap_X86reg(Reg);
|
|
|
|
switch (GetMipsRegState(i))
|
2015-11-15 02:27:06 +00:00
|
|
|
{
|
2016-01-18 11:04:49 +00:00
|
|
|
case CRegInfo::STATE_UNKNOWN: MoveVariableToX86reg(&_GPR[i].UW[0], CRegName::GPR_Lo[i], Reg); break;
|
|
|
|
case CRegInfo::STATE_CONST_32_SIGN: MoveConstToX86reg(GetMipsRegLo(i), Reg); break;
|
|
|
|
case CRegInfo::STATE_MAPPED_32_SIGN:
|
|
|
|
MoveX86RegToX86Reg(GetMipsRegMapLo(i), Reg);
|
|
|
|
m_RegWorkingSet.SetX86Mapped(GetMipsRegMapLo(i), CRegInfo::NotMapped);
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_MAPPED_32_ZERO:
|
|
|
|
if (GetMipsRegMapLo(i) != Reg)
|
|
|
|
{
|
|
|
|
MoveX86RegToX86Reg(GetMipsRegMapLo(i), Reg);
|
|
|
|
m_RegWorkingSet.SetX86Mapped(GetMipsRegMapLo(i), CRegInfo::NotMapped);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_MAPPED_64:
|
2015-11-15 02:27:06 +00:00
|
|
|
MoveX86RegToX86Reg(GetMipsRegMapLo(i), Reg);
|
|
|
|
m_RegWorkingSet.SetX86Mapped(GetMipsRegMapLo(i), CRegInfo::NotMapped);
|
2016-01-18 11:04:49 +00:00
|
|
|
m_RegWorkingSet.SetX86Mapped(GetMipsRegMapHi(i), CRegInfo::NotMapped);
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_CONST_64:
|
|
|
|
CPU_Message("hi %X\nLo %X", GetMipsRegHi(i), GetMipsRegLo(i));
|
|
|
|
default:
|
|
|
|
CPU_Message("Do something with states in SyncRegState\nSTATE_MAPPED_32_SIGN\n%d", GetMipsRegState(i));
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
2016-01-18 11:04:49 +00:00
|
|
|
m_RegWorkingSet.SetMipsRegMapLo(i, Reg);
|
|
|
|
m_RegWorkingSet.SetMipsRegState(i, CRegInfo::STATE_MAPPED_32_SIGN);
|
|
|
|
m_RegWorkingSet.SetX86Mapped(Reg, CRegInfo::GPR_Mapped);
|
|
|
|
m_RegWorkingSet.SetX86MapOrder(Reg, 1);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
2016-01-18 11:04:49 +00:00
|
|
|
break;
|
2015-11-15 02:27:06 +00:00
|
|
|
case CRegInfo::STATE_MAPPED_32_ZERO:
|
|
|
|
{
|
2016-01-18 11:04:49 +00:00
|
|
|
x86Reg Reg = SyncTo.GetMipsRegMapLo(i);
|
|
|
|
UnMap_X86reg(Reg);
|
|
|
|
switch (GetMipsRegState(i))
|
2015-11-15 02:27:06 +00:00
|
|
|
{
|
2016-01-18 11:04:49 +00:00
|
|
|
case CRegInfo::STATE_MAPPED_64:
|
|
|
|
case CRegInfo::STATE_UNKNOWN:
|
|
|
|
MoveVariableToX86reg(&_GPR[i].UW[0], CRegName::GPR_Lo[i], Reg);
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_MAPPED_32_ZERO:
|
2015-11-15 02:27:06 +00:00
|
|
|
MoveX86RegToX86Reg(GetMipsRegMapLo(i), Reg);
|
|
|
|
m_RegWorkingSet.SetX86Mapped(GetMipsRegMapLo(i), CRegInfo::NotMapped);
|
2016-01-18 11:04:49 +00:00
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_MAPPED_32_SIGN:
|
|
|
|
if (g_System->b32BitCore())
|
|
|
|
{
|
|
|
|
MoveX86RegToX86Reg(GetMipsRegMapLo(i), Reg);
|
|
|
|
m_RegWorkingSet.SetX86Mapped(GetMipsRegMapLo(i), CRegInfo::NotMapped);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CPU_Message("Do something with states in SyncRegState\nSTATE_MAPPED_32_ZERO\n%d", GetMipsRegState(i));
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_CONST_32_SIGN:
|
|
|
|
if (!g_System->b32BitCore() && GetMipsRegLo_S(i) < 0)
|
|
|
|
{
|
|
|
|
CPU_Message("Sign Problems in SyncRegState\nSTATE_MAPPED_32_ZERO");
|
|
|
|
CPU_Message("%s: %X", CRegName::GPR[i], GetMipsRegLo_S(i));
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
MoveConstToX86reg(GetMipsRegLo(i), Reg);
|
|
|
|
break;
|
|
|
|
default:
|
2015-11-15 02:27:06 +00:00
|
|
|
CPU_Message("Do something with states in SyncRegState\nSTATE_MAPPED_32_ZERO\n%d", GetMipsRegState(i));
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
2016-01-18 11:04:49 +00:00
|
|
|
m_RegWorkingSet.SetMipsRegMapLo(i, Reg);
|
|
|
|
m_RegWorkingSet.SetMipsRegState(i, SyncTo.GetMipsRegState(i));
|
|
|
|
m_RegWorkingSet.SetX86Mapped(Reg, CRegInfo::GPR_Mapped);
|
|
|
|
m_RegWorkingSet.SetX86MapOrder(Reg, 1);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
2016-01-18 11:04:49 +00:00
|
|
|
break;
|
2015-11-15 02:27:06 +00:00
|
|
|
default:
|
|
|
|
CPU_Message("%d - %d reg: %s (%d)", SyncTo.GetMipsRegState(i), GetMipsRegState(i), CRegName::GPR[i], i);
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
changed = false;
|
|
|
|
}
|
|
|
|
}
|
2010-07-23 10:45:35 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CCodeSection::SetDelaySlot()
|
2012-10-14 01:05:52 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
m_DelaySlot = true;
|
2012-10-14 01:05:52 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 06:55:16 +00:00
|
|
|
void CCodeSection::SetJumpAddress(uint32_t JumpPC, uint32_t TargetPC, bool PermLoop)
|
2012-10-14 01:05:52 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
m_Jump.JumpPC = JumpPC;
|
|
|
|
m_Jump.TargetPC = TargetPC;
|
|
|
|
m_Jump.BranchLabel.Format("0x%08X", TargetPC);
|
|
|
|
m_Jump.PermLoop = PermLoop;
|
2012-10-14 01:05:52 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 06:55:16 +00:00
|
|
|
void CCodeSection::SetContinueAddress(uint32_t JumpPC, uint32_t TargetPC)
|
2012-10-14 01:05:52 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
m_Cont.JumpPC = JumpPC;
|
|
|
|
m_Cont.TargetPC = TargetPC;
|
|
|
|
m_Cont.BranchLabel.Format("0x%08X", TargetPC);
|
2012-10-14 01:05:52 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CCodeSection::CompileCop1Test()
|
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
if (m_RegWorkingSet.FpuBeenUsed())
|
|
|
|
return;
|
2015-05-02 22:14:19 +00:00
|
|
|
|
2015-11-15 02:27:06 +00:00
|
|
|
TestVariable(STATUS_CU1, &g_Reg->STATUS_REGISTER, "STATUS_REGISTER");
|
|
|
|
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::COP1_Unuseable, false, JeLabel32);
|
|
|
|
m_RegWorkingSet.FpuBeenUsed() = true;
|
2010-06-04 06:25:07 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
bool CCodeSection::ParentContinue()
|
2010-10-23 18:53:01 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
if (m_ParentSection.size() > 0)
|
|
|
|
{
|
|
|
|
for (SECTION_LIST::iterator iter = m_ParentSection.begin(); iter != m_ParentSection.end(); iter++)
|
|
|
|
{
|
|
|
|
CCodeSection * Parent = *iter;
|
|
|
|
if (Parent->m_CompiledLocation != NULL) { continue; }
|
|
|
|
if (IsAllParentLoops(Parent, true, m_BlockInfo->NextTest())) { continue; }
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!InheritParentInfo())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2010-10-23 18:53:01 +00:00
|
|
|
}
|
|
|
|
|
2012-10-23 08:06:13 +00:00
|
|
|
/*int TestValue = 0;
|
2015-04-28 22:19:02 +00:00
|
|
|
void TestFunc()
|
2012-10-23 08:06:13 +00:00
|
|
|
{
|
2015-11-09 06:55:16 +00:00
|
|
|
TestValue += 1;
|
|
|
|
if (TestValue >= 4)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-09 06:55:16 +00:00
|
|
|
}
|
2012-10-23 08:06:13 +00:00
|
|
|
}*/
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
bool CCodeSection::GenerateNativeCode(uint32_t Test)
|
2010-05-30 01:54:42 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
if (this == NULL) { return false; }
|
|
|
|
|
|
|
|
if (m_CompiledLocation != NULL)
|
|
|
|
{
|
|
|
|
if (m_Test == Test)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
m_Test = Test;
|
2016-06-27 11:49:15 +00:00
|
|
|
if (m_ContinueSection->GenerateNativeCode(Test)) { return true; }
|
|
|
|
if (m_JumpSection->GenerateNativeCode(Test)) { return true; }
|
2015-11-15 02:27:06 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ParentContinue())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2016-06-28 11:22:30 +00:00
|
|
|
m_CompiledLocation = *g_RecompPos;
|
2015-11-15 02:27:06 +00:00
|
|
|
m_RegWorkingSet = m_RegEnter;
|
|
|
|
m_CompilePC = m_EnterPC;
|
|
|
|
m_NextInstruction = m_DelaySlot ? JUMP : NORMAL;
|
|
|
|
m_Section = this;
|
|
|
|
|
|
|
|
if (m_CompilePC < m_BlockInfo->VAddrFirst())
|
|
|
|
{
|
|
|
|
m_BlockInfo->SetVAddrFirst(m_CompilePC);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t ContinueSectionPC = m_ContinueSection ? m_ContinueSection->m_EnterPC : (uint32_t)-1;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2016-01-18 11:04:49 +00:00
|
|
|
__except_try()
|
2015-11-15 02:27:06 +00:00
|
|
|
{
|
|
|
|
if (!g_MMU->LW_VAddr(m_CompilePC, m_Opcode.Hex))
|
|
|
|
{
|
|
|
|
g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD));
|
|
|
|
}
|
|
|
|
}
|
2016-01-18 11:04:49 +00:00
|
|
|
__except_catch()
|
2015-11-15 02:27:06 +00:00
|
|
|
{
|
|
|
|
g_Notify->FatalError(GS(MSG_UNKNOWN_MEM_ACTION));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_CompilePC > m_BlockInfo->VAddrLast())
|
|
|
|
{
|
|
|
|
m_BlockInfo->SetVAddrLast(m_CompilePC);
|
|
|
|
}
|
|
|
|
/*if (m_CompilePC == 0x803245C4)
|
|
|
|
{
|
|
|
|
X86BreakPoint(__FILEW__,__LINE__);
|
|
|
|
//m_RegWorkingSet.UnMap_AllFPRs();
|
|
|
|
}*/
|
|
|
|
|
|
|
|
/*if (m_CompilePC >= 0x80000000 && m_CompilePC <= 0x80400000 && m_NextInstruction == NORMAL)
|
|
|
|
{
|
|
|
|
m_RegWorkingSet.WriteBackRegisters();
|
|
|
|
UpdateCounters(m_RegWorkingSet,false,true);
|
|
|
|
MoveConstToVariable(m_CompilePC,&g_Reg->m_PROGRAM_COUNTER,"PROGRAM_COUNTER");
|
|
|
|
if (g_SyncSystem) {
|
|
|
|
MoveConstToX86reg((uint32_t)g_BaseSystem,x86_ECX);
|
|
|
|
Call_Direct(AddressOf(&CN64System::SyncSystem), "CN64System::SyncSystem");
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
|
|
|
|
/*if ((m_CompilePC == 0x8031C0E4 || m_CompilePC == 0x8031C118 ||
|
|
|
|
m_CompilePC == 0x8031CD88 || m_CompilePC == 0x8031CE24 ||
|
|
|
|
m_CompilePC == 0x8031CE30 || m_CompilePC == 0x8031CE40) && m_NextInstruction == NORMAL)
|
|
|
|
{
|
|
|
|
m_RegWorkingSet.WriteBackRegisters();
|
|
|
|
UpdateCounters(m_RegWorkingSet,false,true);
|
|
|
|
MoveConstToVariable(m_CompilePC,&g_Reg->m_PROGRAM_COUNTER,"PROGRAM_COUNTER");
|
|
|
|
if (g_SyncSystem) {
|
|
|
|
MoveConstToX86reg((uint32_t)g_BaseSystem,x86_ECX);
|
|
|
|
Call_Direct(AddressOf(&CN64System::SyncSystem), "CN64System::SyncSystem");
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
|
|
|
|
/*if (m_CompilePC == 0x801C1B88)
|
|
|
|
{
|
|
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
|
|
Call_Direct(AddressOf(TestFunc), "TestFunc");
|
|
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
|
|
}*/
|
|
|
|
|
|
|
|
/*if (m_CompilePC >= 0x801C1AF8 && m_CompilePC <= 0x801C1C00 && m_NextInstruction == NORMAL)
|
|
|
|
{
|
|
|
|
UpdateCounters(m_RegWorkingSet,false,true);
|
|
|
|
MoveConstToVariable(m_CompilePC,&g_Reg->m_PROGRAM_COUNTER,"PROGRAM_COUNTER");
|
|
|
|
if (g_SyncSystem) {
|
|
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
|
|
MoveConstToX86reg((uint32_t)g_BaseSystem,x86_ECX);
|
|
|
|
Call_Direct(AddressOf(&CN64System::SyncSystemPC), "CN64System::SyncSystemPC");
|
|
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
|
|
|
|
/*if ((m_CompilePC == 0x80263900) && m_NextInstruction == NORMAL)
|
|
|
|
{
|
|
|
|
X86BreakPoint(__FILEW__,__LINE__);
|
|
|
|
}*/
|
|
|
|
|
|
|
|
/*if ((m_CompilePC >= 0x80325D80 && m_CompilePC <= 0x80325DF0) && m_NextInstruction == NORMAL)
|
|
|
|
{
|
|
|
|
m_RegWorkingSet.WriteBackRegisters();
|
|
|
|
UpdateCounters(m_RegWorkingSet,false,true);
|
|
|
|
MoveConstToVariable(m_CompilePC,&g_Reg->m_PROGRAM_COUNTER,"PROGRAM_COUNTER");
|
|
|
|
if (g_SyncSystem) {
|
|
|
|
MoveConstToX86reg((uint32_t)g_BaseSystem,x86_ECX);
|
|
|
|
Call_Direct(AddressOf(&CN64System::SyncSystem), "CN64System::SyncSystem");
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
/*if ((m_CompilePC == 0x80324E14) && m_NextInstruction == NORMAL)
|
|
|
|
{
|
|
|
|
X86BreakPoint(__FILEW__,__LINE__);
|
|
|
|
}*/
|
|
|
|
|
|
|
|
/*if (m_CompilePC == 0x80324E18 && m_NextInstruction == NORMAL)
|
|
|
|
{
|
|
|
|
m_RegWorkingSet.WriteBackRegisters();
|
|
|
|
UpdateCounters(m_RegWorkingSet,false,true);
|
|
|
|
MoveConstToVariable(m_CompilePC,&g_Reg->m_PROGRAM_COUNTER,"PROGRAM_COUNTER");
|
|
|
|
if (g_SyncSystem) {
|
|
|
|
MoveConstToX86reg((uint32_t)g_BaseSystem,x86_ECX);
|
|
|
|
Call_Direct(AddressOf(&CN64System::SyncSystem), "CN64System::SyncSystem");
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
/*if (m_CompilePC >= 0x80324E00 && m_CompilePC <= 0x80324E18 && m_NextInstruction == NORMAL)
|
|
|
|
{
|
|
|
|
m_RegWorkingSet.WriteBackRegisters();
|
|
|
|
UpdateCounters(m_RegWorkingSet,false,true);
|
|
|
|
MoveConstToVariable(m_CompilePC,&g_Reg->m_PROGRAM_COUNTER,"PROGRAM_COUNTER");
|
|
|
|
if (g_SyncSystem) {
|
|
|
|
MoveConstToX86reg((uint32_t)g_BaseSystem,x86_ECX);
|
|
|
|
Call_Direct(AddressOf(&CN64System::SyncSystem), "CN64System::SyncSystem");
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
/* if (m_CompilePC == 0x803245CC && m_NextInstruction == NORMAL)
|
|
|
|
{
|
|
|
|
//m_RegWorkingSet.UnMap_AllFPRs();
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
//X86HardBreakPoint();
|
|
|
|
//X86BreakPoint(__FILEW__,__LINE__);
|
|
|
|
//m_RegWorkingSet.UnMap_AllFPRs();
|
|
|
|
}*/
|
|
|
|
/*if (m_CompilePC >= 0x80179DC4 && m_CompilePC <= 0x80179DF0 && m_NextInstruction == NORMAL)
|
|
|
|
{
|
|
|
|
m_RegWorkingSet.UnMap_AllFPRs();
|
|
|
|
}*/
|
|
|
|
|
|
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
m_RegWorkingSet.ResetX86Protection();
|
|
|
|
|
|
|
|
switch (m_Opcode.op)
|
|
|
|
{
|
|
|
|
case R4300i_SPECIAL:
|
|
|
|
switch (m_Opcode.funct)
|
|
|
|
{
|
|
|
|
case R4300i_SPECIAL_SLL: SPECIAL_SLL(); break;
|
|
|
|
case R4300i_SPECIAL_SRL: SPECIAL_SRL(); break;
|
|
|
|
case R4300i_SPECIAL_SRA: SPECIAL_SRA(); break;
|
|
|
|
case R4300i_SPECIAL_SLLV: SPECIAL_SLLV(); break;
|
|
|
|
case R4300i_SPECIAL_SRLV: SPECIAL_SRLV(); break;
|
|
|
|
case R4300i_SPECIAL_SRAV: SPECIAL_SRAV(); break;
|
|
|
|
case R4300i_SPECIAL_JR: SPECIAL_JR(); break;
|
|
|
|
case R4300i_SPECIAL_JALR: SPECIAL_JALR(); break;
|
|
|
|
case R4300i_SPECIAL_MFLO: SPECIAL_MFLO(); break;
|
|
|
|
case R4300i_SPECIAL_SYSCALL: SPECIAL_SYSCALL(); break;
|
|
|
|
case R4300i_SPECIAL_MTLO: SPECIAL_MTLO(); break;
|
|
|
|
case R4300i_SPECIAL_MFHI: SPECIAL_MFHI(); break;
|
|
|
|
case R4300i_SPECIAL_MTHI: SPECIAL_MTHI(); break;
|
|
|
|
case R4300i_SPECIAL_DSLLV: SPECIAL_DSLLV(); break;
|
|
|
|
case R4300i_SPECIAL_DSRLV: SPECIAL_DSRLV(); break;
|
|
|
|
case R4300i_SPECIAL_DSRAV: SPECIAL_DSRAV(); break;
|
|
|
|
case R4300i_SPECIAL_MULT: SPECIAL_MULT(); break;
|
|
|
|
case R4300i_SPECIAL_DIV: SPECIAL_DIV(); break;
|
|
|
|
case R4300i_SPECIAL_DIVU: SPECIAL_DIVU(); break;
|
|
|
|
case R4300i_SPECIAL_MULTU: SPECIAL_MULTU(); break;
|
|
|
|
case R4300i_SPECIAL_DMULT: SPECIAL_DMULT(); break;
|
|
|
|
case R4300i_SPECIAL_DMULTU: SPECIAL_DMULTU(); break;
|
|
|
|
case R4300i_SPECIAL_DDIV: SPECIAL_DDIV(); break;
|
|
|
|
case R4300i_SPECIAL_DDIVU: SPECIAL_DDIVU(); break;
|
|
|
|
case R4300i_SPECIAL_ADD: SPECIAL_ADD(); break;
|
|
|
|
case R4300i_SPECIAL_ADDU: SPECIAL_ADDU(); break;
|
|
|
|
case R4300i_SPECIAL_SUB: SPECIAL_SUB(); break;
|
|
|
|
case R4300i_SPECIAL_SUBU: SPECIAL_SUBU(); break;
|
|
|
|
case R4300i_SPECIAL_AND: SPECIAL_AND(); break;
|
|
|
|
case R4300i_SPECIAL_OR: SPECIAL_OR(); break;
|
|
|
|
case R4300i_SPECIAL_XOR: SPECIAL_XOR(); break;
|
|
|
|
case R4300i_SPECIAL_NOR: SPECIAL_NOR(); break;
|
|
|
|
case R4300i_SPECIAL_SLT: SPECIAL_SLT(); break;
|
|
|
|
case R4300i_SPECIAL_SLTU: SPECIAL_SLTU(); break;
|
|
|
|
case R4300i_SPECIAL_DADD: SPECIAL_DADD(); break;
|
|
|
|
case R4300i_SPECIAL_DADDU: SPECIAL_DADDU(); break;
|
|
|
|
case R4300i_SPECIAL_DSUB: SPECIAL_DSUB(); break;
|
|
|
|
case R4300i_SPECIAL_DSUBU: SPECIAL_DSUBU(); break;
|
|
|
|
case R4300i_SPECIAL_DSLL: SPECIAL_DSLL(); break;
|
|
|
|
case R4300i_SPECIAL_DSRL: SPECIAL_DSRL(); break;
|
|
|
|
case R4300i_SPECIAL_DSRA: SPECIAL_DSRA(); break;
|
|
|
|
case R4300i_SPECIAL_DSLL32: SPECIAL_DSLL32(); break;
|
|
|
|
case R4300i_SPECIAL_DSRL32: SPECIAL_DSRL32(); break;
|
|
|
|
case R4300i_SPECIAL_DSRA32: SPECIAL_DSRA32(); break;
|
|
|
|
default:
|
|
|
|
UnknownOpcode(); break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R4300i_REGIMM:
|
|
|
|
switch (m_Opcode.rt)
|
|
|
|
{
|
|
|
|
case R4300i_REGIMM_BLTZ:Compile_Branch(BLTZ_Compare, BranchTypeRs, false); break;
|
|
|
|
case R4300i_REGIMM_BGEZ:Compile_Branch(BGEZ_Compare, BranchTypeRs, false); break;
|
|
|
|
case R4300i_REGIMM_BLTZL:Compile_BranchLikely(BLTZ_Compare, false); break;
|
|
|
|
case R4300i_REGIMM_BGEZL:Compile_BranchLikely(BGEZ_Compare, false); break;
|
|
|
|
case R4300i_REGIMM_BLTZAL:Compile_Branch(BLTZ_Compare, BranchTypeRs, true); break;
|
|
|
|
case R4300i_REGIMM_BGEZAL:Compile_Branch(BGEZ_Compare, BranchTypeRs, true); break;
|
|
|
|
default:
|
|
|
|
UnknownOpcode(); break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R4300i_BEQ: Compile_Branch(BEQ_Compare, BranchTypeRsRt, false); break;
|
|
|
|
case R4300i_BNE: Compile_Branch(BNE_Compare, BranchTypeRsRt, false); break;
|
|
|
|
case R4300i_BGTZ:Compile_Branch(BGTZ_Compare, BranchTypeRs, false); break;
|
|
|
|
case R4300i_BLEZ:Compile_Branch(BLEZ_Compare, BranchTypeRs, false); break;
|
|
|
|
case R4300i_J: J(); break;
|
|
|
|
case R4300i_JAL: JAL(); break;
|
|
|
|
case R4300i_ADDI: ADDI(); break;
|
|
|
|
case R4300i_ADDIU: ADDIU(); break;
|
|
|
|
case R4300i_SLTI: SLTI(); break;
|
|
|
|
case R4300i_SLTIU: SLTIU(); break;
|
|
|
|
case R4300i_ANDI: ANDI(); break;
|
|
|
|
case R4300i_ORI: ORI(); break;
|
|
|
|
case R4300i_XORI: XORI(); break;
|
|
|
|
case R4300i_LUI: LUI(); break;
|
|
|
|
case R4300i_CP0:
|
|
|
|
switch (m_Opcode.rs)
|
|
|
|
{
|
|
|
|
case R4300i_COP0_MF: COP0_MF(); break;
|
|
|
|
case R4300i_COP0_MT: COP0_MT(); break;
|
|
|
|
default:
|
|
|
|
if ((m_Opcode.rs & 0x10) != 0)
|
|
|
|
{
|
|
|
|
switch (m_Opcode.funct)
|
|
|
|
{
|
|
|
|
case R4300i_COP0_CO_TLBR: COP0_CO_TLBR(); break;
|
|
|
|
case R4300i_COP0_CO_TLBWI: COP0_CO_TLBWI(); break;
|
|
|
|
case R4300i_COP0_CO_TLBWR: COP0_CO_TLBWR(); break;
|
|
|
|
case R4300i_COP0_CO_TLBP: COP0_CO_TLBP(); break;
|
|
|
|
case R4300i_COP0_CO_ERET: COP0_CO_ERET(); break;
|
|
|
|
default: UnknownOpcode(); break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UnknownOpcode();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R4300i_CP1:
|
|
|
|
switch (m_Opcode.rs)
|
|
|
|
{
|
|
|
|
case R4300i_COP1_MF: COP1_MF(); break;
|
|
|
|
case R4300i_COP1_DMF: COP1_DMF(); break;
|
|
|
|
case R4300i_COP1_CF: COP1_CF(); break;
|
|
|
|
case R4300i_COP1_MT: COP1_MT(); break;
|
|
|
|
case R4300i_COP1_DMT: COP1_DMT(); break;
|
|
|
|
case R4300i_COP1_CT: COP1_CT(); break;
|
|
|
|
case R4300i_COP1_BC:
|
|
|
|
switch (m_Opcode.ft)
|
|
|
|
{
|
|
|
|
case R4300i_COP1_BC_BCF: Compile_Branch(COP1_BCF_Compare, BranchTypeCop1, false); break;
|
|
|
|
case R4300i_COP1_BC_BCT: Compile_Branch(COP1_BCT_Compare, BranchTypeCop1, false); break;
|
|
|
|
case R4300i_COP1_BC_BCFL: Compile_BranchLikely(COP1_BCF_Compare, false); break;
|
|
|
|
case R4300i_COP1_BC_BCTL: Compile_BranchLikely(COP1_BCT_Compare, false); break;
|
|
|
|
default:
|
|
|
|
UnknownOpcode(); break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R4300i_COP1_S:
|
|
|
|
switch (m_Opcode.funct)
|
|
|
|
{
|
|
|
|
case R4300i_COP1_FUNCT_ADD: COP1_S_ADD(); break;
|
|
|
|
case R4300i_COP1_FUNCT_SUB: COP1_S_SUB(); break;
|
|
|
|
case R4300i_COP1_FUNCT_MUL: COP1_S_MUL(); break;
|
|
|
|
case R4300i_COP1_FUNCT_DIV: COP1_S_DIV(); break;
|
|
|
|
case R4300i_COP1_FUNCT_ABS: COP1_S_ABS(); break;
|
|
|
|
case R4300i_COP1_FUNCT_NEG: COP1_S_NEG(); break;
|
|
|
|
case R4300i_COP1_FUNCT_SQRT: COP1_S_SQRT(); break;
|
|
|
|
case R4300i_COP1_FUNCT_MOV: COP1_S_MOV(); break;
|
2016-05-23 06:28:07 +00:00
|
|
|
case R4300i_COP1_FUNCT_ROUND_L: COP1_S_ROUND_L(); break;
|
2015-11-15 02:27:06 +00:00
|
|
|
case R4300i_COP1_FUNCT_TRUNC_L: COP1_S_TRUNC_L(); break;
|
|
|
|
case R4300i_COP1_FUNCT_CEIL_L: COP1_S_CEIL_L(); break; //added by Witten
|
|
|
|
case R4300i_COP1_FUNCT_FLOOR_L: COP1_S_FLOOR_L(); break; //added by Witten
|
|
|
|
case R4300i_COP1_FUNCT_ROUND_W: COP1_S_ROUND_W(); break;
|
|
|
|
case R4300i_COP1_FUNCT_TRUNC_W: COP1_S_TRUNC_W(); break;
|
|
|
|
case R4300i_COP1_FUNCT_CEIL_W: COP1_S_CEIL_W(); break; //added by Witten
|
|
|
|
case R4300i_COP1_FUNCT_FLOOR_W: COP1_S_FLOOR_W(); break;
|
|
|
|
case R4300i_COP1_FUNCT_CVT_D: COP1_S_CVT_D(); break;
|
|
|
|
case R4300i_COP1_FUNCT_CVT_W: COP1_S_CVT_W(); break;
|
|
|
|
case R4300i_COP1_FUNCT_CVT_L: COP1_S_CVT_L(); break;
|
|
|
|
case R4300i_COP1_FUNCT_C_F: case R4300i_COP1_FUNCT_C_UN:
|
|
|
|
case R4300i_COP1_FUNCT_C_EQ: case R4300i_COP1_FUNCT_C_UEQ:
|
|
|
|
case R4300i_COP1_FUNCT_C_OLT: case R4300i_COP1_FUNCT_C_ULT:
|
|
|
|
case R4300i_COP1_FUNCT_C_OLE: case R4300i_COP1_FUNCT_C_ULE:
|
|
|
|
case R4300i_COP1_FUNCT_C_SF: case R4300i_COP1_FUNCT_C_NGLE:
|
|
|
|
case R4300i_COP1_FUNCT_C_SEQ: case R4300i_COP1_FUNCT_C_NGL:
|
|
|
|
case R4300i_COP1_FUNCT_C_LT: case R4300i_COP1_FUNCT_C_NGE:
|
|
|
|
case R4300i_COP1_FUNCT_C_LE: case R4300i_COP1_FUNCT_C_NGT:
|
|
|
|
COP1_S_CMP(); break;
|
|
|
|
default:
|
|
|
|
UnknownOpcode(); break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R4300i_COP1_D:
|
|
|
|
switch (m_Opcode.funct)
|
|
|
|
{
|
|
|
|
case R4300i_COP1_FUNCT_ADD: COP1_D_ADD(); break;
|
|
|
|
case R4300i_COP1_FUNCT_SUB: COP1_D_SUB(); break;
|
|
|
|
case R4300i_COP1_FUNCT_MUL: COP1_D_MUL(); break;
|
|
|
|
case R4300i_COP1_FUNCT_DIV: COP1_D_DIV(); break;
|
|
|
|
case R4300i_COP1_FUNCT_ABS: COP1_D_ABS(); break;
|
|
|
|
case R4300i_COP1_FUNCT_NEG: COP1_D_NEG(); break;
|
|
|
|
case R4300i_COP1_FUNCT_SQRT: COP1_D_SQRT(); break;
|
|
|
|
case R4300i_COP1_FUNCT_MOV: COP1_D_MOV(); break;
|
2016-05-23 06:47:02 +00:00
|
|
|
case R4300i_COP1_FUNCT_ROUND_L: COP1_D_ROUND_L(); break;
|
2015-11-15 02:27:06 +00:00
|
|
|
case R4300i_COP1_FUNCT_TRUNC_L: COP1_D_TRUNC_L(); break; //added by Witten
|
|
|
|
case R4300i_COP1_FUNCT_CEIL_L: COP1_D_CEIL_L(); break; //added by Witten
|
|
|
|
case R4300i_COP1_FUNCT_FLOOR_L: COP1_D_FLOOR_L(); break; //added by Witten
|
|
|
|
case R4300i_COP1_FUNCT_ROUND_W: COP1_D_ROUND_W(); break;
|
|
|
|
case R4300i_COP1_FUNCT_TRUNC_W: COP1_D_TRUNC_W(); break;
|
|
|
|
case R4300i_COP1_FUNCT_CEIL_W: COP1_D_CEIL_W(); break; //added by Witten
|
|
|
|
case R4300i_COP1_FUNCT_FLOOR_W: COP1_D_FLOOR_W(); break; //added by Witten
|
|
|
|
case R4300i_COP1_FUNCT_CVT_S: COP1_D_CVT_S(); break;
|
|
|
|
case R4300i_COP1_FUNCT_CVT_W: COP1_D_CVT_W(); break;
|
|
|
|
case R4300i_COP1_FUNCT_CVT_L: COP1_D_CVT_L(); break;
|
|
|
|
case R4300i_COP1_FUNCT_C_F: case R4300i_COP1_FUNCT_C_UN:
|
|
|
|
case R4300i_COP1_FUNCT_C_EQ: case R4300i_COP1_FUNCT_C_UEQ:
|
|
|
|
case R4300i_COP1_FUNCT_C_OLT: case R4300i_COP1_FUNCT_C_ULT:
|
|
|
|
case R4300i_COP1_FUNCT_C_OLE: case R4300i_COP1_FUNCT_C_ULE:
|
|
|
|
case R4300i_COP1_FUNCT_C_SF: case R4300i_COP1_FUNCT_C_NGLE:
|
|
|
|
case R4300i_COP1_FUNCT_C_SEQ: case R4300i_COP1_FUNCT_C_NGL:
|
|
|
|
case R4300i_COP1_FUNCT_C_LT: case R4300i_COP1_FUNCT_C_NGE:
|
|
|
|
case R4300i_COP1_FUNCT_C_LE: case R4300i_COP1_FUNCT_C_NGT:
|
|
|
|
COP1_D_CMP(); break;
|
|
|
|
default:
|
|
|
|
UnknownOpcode(); break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R4300i_COP1_W:
|
|
|
|
switch (m_Opcode.funct)
|
|
|
|
{
|
|
|
|
case R4300i_COP1_FUNCT_CVT_S: COP1_W_CVT_S(); break;
|
|
|
|
case R4300i_COP1_FUNCT_CVT_D: COP1_W_CVT_D(); break;
|
|
|
|
default:
|
|
|
|
UnknownOpcode(); break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R4300i_COP1_L:
|
|
|
|
switch (m_Opcode.funct)
|
|
|
|
{
|
|
|
|
case R4300i_COP1_FUNCT_CVT_S: COP1_L_CVT_S(); break;
|
|
|
|
case R4300i_COP1_FUNCT_CVT_D: COP1_L_CVT_D(); break;
|
|
|
|
default:
|
|
|
|
UnknownOpcode(); break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UnknownOpcode(); break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R4300i_BEQL: Compile_BranchLikely(BEQ_Compare, false); break;
|
|
|
|
case R4300i_BNEL: Compile_BranchLikely(BNE_Compare, false); break;
|
|
|
|
case R4300i_BGTZL:Compile_BranchLikely(BGTZ_Compare, false); break;
|
|
|
|
case R4300i_BLEZL:Compile_BranchLikely(BLEZ_Compare, false); break;
|
|
|
|
case R4300i_DADDIU: DADDIU(); break;
|
2016-06-29 13:40:36 +00:00
|
|
|
case R4300i_LDL: LDL(); break;
|
|
|
|
case R4300i_LDR: LDR(); break;
|
|
|
|
case R4300i_LB: LB(); break;
|
|
|
|
case R4300i_LH: LH(); break;
|
|
|
|
case R4300i_LWL: LWL(); break;
|
|
|
|
case R4300i_LW: LW(); break;
|
|
|
|
case R4300i_LBU: LBU(); break;
|
|
|
|
case R4300i_LHU: LHU(); break;
|
|
|
|
case R4300i_LWR: LWR(); break;
|
|
|
|
case R4300i_LWU: LWU(); break; //added by Witten
|
|
|
|
case R4300i_SB: SB(); break;
|
|
|
|
case R4300i_SH: SH(); break;
|
|
|
|
case R4300i_SWL: SWL(); break;
|
|
|
|
case R4300i_SW: SW(); break;
|
|
|
|
case R4300i_SWR: SWR(); break;
|
|
|
|
case R4300i_SDL: SDL(); break;
|
|
|
|
case R4300i_SDR: SDR(); break;
|
2015-11-15 02:27:06 +00:00
|
|
|
case R4300i_CACHE: CACHE(); break;
|
2016-06-29 13:40:36 +00:00
|
|
|
case R4300i_LL: LL(); break;
|
|
|
|
case R4300i_LWC1: LWC1(); break;
|
|
|
|
case R4300i_LDC1: LDC1(); break;
|
|
|
|
case R4300i_SC: SC(); break;
|
|
|
|
case R4300i_LD: LD(); break;
|
|
|
|
case R4300i_SWC1: SWC1(); break;
|
|
|
|
case R4300i_SDC1: SDC1(); break;
|
|
|
|
case R4300i_SD: SD(); break;
|
2015-11-15 02:27:06 +00:00
|
|
|
default:
|
|
|
|
UnknownOpcode(); break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!g_System->bRegCaching()) { m_RegWorkingSet.WriteBackRegisters(); }
|
|
|
|
m_RegWorkingSet.UnMap_AllFPRs();
|
|
|
|
|
|
|
|
if ((m_CompilePC & 0xFFC) == 0xFFC)
|
|
|
|
{
|
|
|
|
if (m_NextInstruction == DO_DELAY_SLOT)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
if (m_NextInstruction == NORMAL)
|
|
|
|
{
|
|
|
|
if (m_DelaySlot)
|
|
|
|
{
|
|
|
|
CompileExit(m_CompilePC, m_Jump.TargetPC, m_RegWorkingSet, CExitInfo::Normal, true, NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CompileExit(m_CompilePC, m_CompilePC + 4, m_RegWorkingSet, CExitInfo::Normal, true, NULL);
|
|
|
|
}
|
|
|
|
m_NextInstruction = END_BLOCK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (m_NextInstruction)
|
|
|
|
{
|
|
|
|
case NORMAL:
|
|
|
|
m_CompilePC += 4;
|
|
|
|
break;
|
|
|
|
case DO_DELAY_SLOT:
|
|
|
|
m_NextInstruction = DELAY_SLOT;
|
|
|
|
m_CompilePC += 4;
|
|
|
|
break;
|
|
|
|
case DELAY_SLOT:
|
|
|
|
m_NextInstruction = DELAY_SLOT_DONE;
|
|
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
|
|
|
|
m_CompilePC -= 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_DelaySlot)
|
|
|
|
{
|
|
|
|
if ((CompilePC() & 0xFFC) != 0xFFC && m_Jump.JumpPC != (uint32_t)-1)
|
|
|
|
{
|
|
|
|
m_CompilePC = m_Jump.JumpPC;
|
|
|
|
m_Jump.RegSet = m_RegWorkingSet;
|
|
|
|
m_Jump.FallThrough = true;
|
|
|
|
GenerateSectionLinkage();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CompileExit(m_Jump.JumpPC, m_Jump.TargetPC, m_RegWorkingSet, CExitInfo::Normal, true, NULL);
|
|
|
|
}
|
|
|
|
m_NextInstruction = END_BLOCK;
|
|
|
|
}
|
|
|
|
else if (m_NextInstruction != END_BLOCK && m_CompilePC == ContinueSectionPC)
|
|
|
|
{
|
|
|
|
if (m_NextInstruction != NORMAL)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
m_CompilePC -= 4;
|
|
|
|
m_Cont.RegSet = m_RegWorkingSet;
|
|
|
|
m_Cont.FallThrough = true;
|
|
|
|
m_Cont.JumpPC = m_CompilePC;
|
|
|
|
GenerateSectionLinkage();
|
|
|
|
m_NextInstruction = END_BLOCK;
|
|
|
|
}
|
|
|
|
} while (m_NextInstruction != END_BLOCK);
|
|
|
|
return true;
|
2010-05-30 01:54:42 +00:00
|
|
|
}
|
2010-07-23 10:45:35 +00:00
|
|
|
|
2015-11-09 06:55:16 +00:00
|
|
|
void CCodeSection::AddParent(CCodeSection * Parent)
|
2010-07-23 10:45:35 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
if (this == NULL) { return; }
|
|
|
|
if (Parent == NULL)
|
|
|
|
{
|
|
|
|
m_RegWorkingSet = m_RegEnter;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check to see if we already have the parent in the list
|
|
|
|
for (SECTION_LIST::iterator iter = m_ParentSection.begin(); iter != m_ParentSection.end(); iter++)
|
|
|
|
{
|
|
|
|
if (*iter == Parent)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_ParentSection.push_back(Parent);
|
|
|
|
|
|
|
|
if (m_ParentSection.size() == 1)
|
|
|
|
{
|
|
|
|
if (Parent->m_ContinueSection == this)
|
|
|
|
{
|
|
|
|
m_RegEnter = Parent->m_Cont.RegSet;
|
|
|
|
}
|
|
|
|
else if (Parent->m_JumpSection == this)
|
|
|
|
{
|
|
|
|
m_RegEnter = Parent->m_Jump.RegSet;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-12-23 20:38:50 +00:00
|
|
|
g_Notify->DisplayError("How are these sections joined?????");
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
m_RegWorkingSet = m_RegEnter;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (Parent->m_ContinueSection == this)
|
|
|
|
{
|
|
|
|
TestRegConstantStates(Parent->m_Cont.RegSet, m_RegEnter);
|
|
|
|
}
|
|
|
|
if (Parent->m_JumpSection == this)
|
|
|
|
{
|
|
|
|
TestRegConstantStates(Parent->m_Jump.RegSet, m_RegEnter);
|
|
|
|
}
|
|
|
|
m_RegWorkingSet = m_RegEnter;
|
|
|
|
}
|
2010-07-23 10:45:35 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 06:55:16 +00:00
|
|
|
void CCodeSection::SwitchParent(CCodeSection * OldParent, CCodeSection * NewParent)
|
2012-10-14 01:05:52 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
if (this == NULL) { return; }
|
|
|
|
|
|
|
|
bool bFoundOldParent = false;
|
|
|
|
for (SECTION_LIST::iterator iter = m_ParentSection.begin(); iter != m_ParentSection.end(); iter++)
|
|
|
|
{
|
|
|
|
if (*iter != OldParent)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
bFoundOldParent = true;
|
|
|
|
m_ParentSection.erase(iter);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bFoundOldParent)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
m_ParentSection.push_back(NewParent);
|
2012-10-14 01:05:52 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 06:55:16 +00:00
|
|
|
void CCodeSection::TestRegConstantStates(CRegInfo & Base, CRegInfo & Reg)
|
2010-07-23 10:45:35 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
for (int i = 0; i < 32; i++)
|
|
|
|
{
|
|
|
|
if (Reg.GetMipsRegState(i) != Base.GetMipsRegState(i))
|
|
|
|
{
|
|
|
|
Reg.SetMipsRegState(i, CRegInfo::STATE_UNKNOWN);
|
|
|
|
}
|
|
|
|
if (Reg.IsConst(i))
|
|
|
|
{
|
|
|
|
if (Reg.Is32Bit(i))
|
|
|
|
{
|
|
|
|
if (Reg.GetMipsRegLo(i) != Base.GetMipsRegLo(i))
|
|
|
|
{
|
|
|
|
Reg.SetMipsRegState(i, CRegInfo::STATE_UNKNOWN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Reg.GetMipsReg(i) != Base.GetMipsReg(i))
|
|
|
|
{
|
|
|
|
Reg.SetMipsRegState(i, CRegInfo::STATE_UNKNOWN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-07-23 10:45:35 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 06:55:16 +00:00
|
|
|
void CCodeSection::DetermineLoop(uint32_t Test, uint32_t Test2, uint32_t TestID)
|
2010-07-23 10:45:35 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
if (this == NULL) { return; }
|
|
|
|
|
|
|
|
if (m_SectionID == TestID)
|
|
|
|
{
|
|
|
|
if (m_Test2 != Test2)
|
|
|
|
{
|
|
|
|
m_Test2 = Test2;
|
|
|
|
m_ContinueSection->DetermineLoop(Test, Test2, TestID);
|
|
|
|
m_JumpSection->DetermineLoop(Test, Test2, TestID);
|
|
|
|
|
|
|
|
if (m_Test != Test)
|
|
|
|
{
|
|
|
|
m_Test = Test;
|
|
|
|
if (m_ContinueSection != NULL)
|
|
|
|
{
|
|
|
|
m_ContinueSection->DetermineLoop(Test, m_BlockInfo->NextTest(), m_ContinueSection->m_SectionID);
|
|
|
|
}
|
|
|
|
if (m_JumpSection != NULL)
|
|
|
|
{
|
|
|
|
m_JumpSection->DetermineLoop(Test, m_BlockInfo->NextTest(), m_JumpSection->m_SectionID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_InLoop = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_Test2 != Test2)
|
|
|
|
{
|
|
|
|
m_Test2 = Test2;
|
|
|
|
m_ContinueSection->DetermineLoop(Test, Test2, TestID);
|
|
|
|
m_JumpSection->DetermineLoop(Test, Test2, TestID);
|
|
|
|
}
|
|
|
|
}
|
2010-07-23 10:45:35 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 06:55:16 +00:00
|
|
|
CCodeSection * CCodeSection::ExistingSection(uint32_t Addr, uint32_t Test)
|
2010-07-23 10:45:35 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
if (this == NULL) { return NULL; }
|
|
|
|
if (m_EnterPC == Addr && m_LinkAllowed)
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
if (m_Test == Test) { return NULL; }
|
|
|
|
m_Test = Test;
|
|
|
|
|
|
|
|
CCodeSection * Section = m_JumpSection->ExistingSection(Addr, Test);
|
|
|
|
if (Section != NULL) { return Section; }
|
|
|
|
Section = m_ContinueSection->ExistingSection(Addr, Test);
|
|
|
|
if (Section != NULL) { return Section; }
|
|
|
|
|
|
|
|
return NULL;
|
2010-07-23 10:45:35 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 06:55:16 +00:00
|
|
|
bool CCodeSection::SectionAccessible(uint32_t SectionId, uint32_t Test)
|
2010-10-23 18:53:01 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
if (this == NULL) { return false; }
|
|
|
|
if (m_SectionID == SectionId)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_Test == Test) { return false; }
|
|
|
|
m_Test = Test;
|
|
|
|
|
|
|
|
if (m_ContinueSection->SectionAccessible(SectionId, Test))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return m_JumpSection->SectionAccessible(SectionId, Test);
|
2010-10-23 18:53:01 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 06:55:16 +00:00
|
|
|
void CCodeSection::UnlinkParent(CCodeSection * Parent, bool ContinueSection)
|
2010-10-23 18:53:01 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
if (this == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-01-18 11:04:49 +00:00
|
|
|
CPU_Message("%s: Section %d Parent: %d ContinueSection = %s", __FUNCTION__, m_SectionID, Parent->m_SectionID, ContinueSection ? "Yes" : "No");
|
2015-11-15 02:27:06 +00:00
|
|
|
if (Parent->m_ContinueSection == this && Parent->m_JumpSection == this)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SECTION_LIST::iterator iter = m_ParentSection.begin();
|
|
|
|
while (iter != m_ParentSection.end())
|
|
|
|
{
|
|
|
|
CCodeSection * ParentIter = *iter;
|
|
|
|
if (ParentIter == Parent && (Parent->m_ContinueSection != this || Parent->m_JumpSection != this))
|
|
|
|
{
|
|
|
|
m_ParentSection.erase(iter);
|
|
|
|
iter = m_ParentSection.begin();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
iter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ContinueSection && Parent->m_ContinueSection == this)
|
|
|
|
{
|
|
|
|
Parent->m_ContinueSection = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ContinueSection && Parent->m_JumpSection == this)
|
|
|
|
{
|
|
|
|
Parent->m_JumpSection = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool bRemove = false;
|
|
|
|
if (m_ParentSection.size() > 0)
|
|
|
|
{
|
|
|
|
if (!m_BlockInfo->SectionAccessible(m_SectionID))
|
|
|
|
{
|
|
|
|
for (SECTION_LIST::iterator iter = m_ParentSection.begin(); iter != m_ParentSection.end(); iter++)
|
|
|
|
{
|
|
|
|
CCodeSection * ParentIter = *iter;
|
|
|
|
if (ParentIter->m_ContinueSection == this)
|
|
|
|
{
|
|
|
|
if (ParentIter->m_CompiledLocation)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
ParentIter->m_ContinueSection = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ParentIter->m_JumpSection == this)
|
|
|
|
{
|
|
|
|
if (ParentIter->m_CompiledLocation)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
ParentIter->m_JumpSection = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bRemove = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bRemove = true;
|
|
|
|
}
|
|
|
|
if (bRemove)
|
|
|
|
{
|
|
|
|
if (m_JumpSection != NULL)
|
|
|
|
{
|
|
|
|
m_JumpSection->UnlinkParent(this, false);
|
|
|
|
}
|
|
|
|
if (m_ContinueSection != NULL)
|
|
|
|
{
|
|
|
|
m_ContinueSection->UnlinkParent(this, true);
|
|
|
|
}
|
|
|
|
}
|
2010-10-23 18:53:01 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 06:55:16 +00:00
|
|
|
bool CCodeSection::IsAllParentLoops(CCodeSection * Parent, bool IgnoreIfCompiled, uint32_t Test)
|
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
if (IgnoreIfCompiled && Parent->m_CompiledLocation != NULL) { return true; }
|
|
|
|
if (!m_InLoop) { return false; }
|
|
|
|
if (!Parent->m_InLoop) { return false; }
|
|
|
|
if (Parent->m_ParentSection.empty()) { return false; }
|
|
|
|
if (this == Parent) { return true; }
|
|
|
|
if (Parent->m_Test == Test) { return true; }
|
|
|
|
Parent->m_Test = Test;
|
|
|
|
|
|
|
|
for (SECTION_LIST::iterator iter = Parent->m_ParentSection.begin(); iter != Parent->m_ParentSection.end(); iter++)
|
|
|
|
{
|
|
|
|
CCodeSection * ParentSection = *iter;
|
|
|
|
if (!IsAllParentLoops(ParentSection, IgnoreIfCompiled, Test)) { return false; }
|
|
|
|
}
|
|
|
|
return true;
|
2010-10-23 18:53:01 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
bool CCodeSection::SetupRegisterForLoop()
|
2012-10-14 01:05:52 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
CRegInfo OriginalReg = m_RegWorkingSet;
|
|
|
|
if (!LoopAnalysis(m_BlockInfo, this).SetupRegisterForLoop())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for (int i = 1; i < 32; i++)
|
|
|
|
{
|
|
|
|
if (OriginalReg.GetMipsRegState(i) != m_RegEnter.GetMipsRegState(i))
|
|
|
|
{
|
|
|
|
UnMap_GPR(i, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2012-10-14 01:05:52 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
bool CCodeSection::InheritParentInfo()
|
2015-11-09 06:55:16 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
if (m_CompiledLocation == NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
m_CompiledLocation = *g_RecompPos;
|
2015-11-15 02:27:06 +00:00
|
|
|
DisplaySectionInformation();
|
|
|
|
m_CompiledLocation = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DisplaySectionInformation();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_ParentSection.empty())
|
|
|
|
{
|
|
|
|
m_RegWorkingSet = m_RegEnter;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_ParentSection.size() == 1)
|
|
|
|
{
|
|
|
|
CCodeSection * Parent = *(m_ParentSection.begin());
|
|
|
|
if (Parent->m_CompiledLocation == NULL)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
CJumpInfo * JumpInfo = this == Parent->m_ContinueSection ? &Parent->m_Cont : &Parent->m_Jump;
|
|
|
|
|
|
|
|
m_RegEnter = JumpInfo->RegSet;
|
|
|
|
if (JumpInfo->LinkLocation != NULL)
|
|
|
|
{
|
|
|
|
CPU_Message(" Section_%d:", m_SectionID);
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo->LinkLocation, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
if (JumpInfo->LinkLocation2 != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo->LinkLocation2, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
m_RegWorkingSet = m_RegEnter;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Multiple Parents
|
|
|
|
BLOCK_PARENT_LIST ParentList;
|
|
|
|
SECTION_LIST::iterator iter;
|
|
|
|
for (iter = m_ParentSection.begin(); iter != m_ParentSection.end(); iter++)
|
|
|
|
{
|
|
|
|
CCodeSection * Parent = *iter;
|
|
|
|
BLOCK_PARENT BlockParent;
|
|
|
|
|
|
|
|
if (Parent->m_CompiledLocation == NULL) { continue; }
|
|
|
|
if (Parent->m_JumpSection != Parent->m_ContinueSection)
|
|
|
|
{
|
|
|
|
BlockParent.Parent = Parent;
|
|
|
|
BlockParent.JumpInfo = this == Parent->m_ContinueSection ? &Parent->m_Cont : &Parent->m_Jump;
|
|
|
|
ParentList.push_back(BlockParent);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BlockParent.Parent = Parent;
|
|
|
|
BlockParent.JumpInfo = &Parent->m_Cont;
|
|
|
|
ParentList.push_back(BlockParent);
|
|
|
|
BlockParent.Parent = Parent;
|
|
|
|
BlockParent.JumpInfo = &Parent->m_Jump;
|
|
|
|
ParentList.push_back(BlockParent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
size_t NoOfCompiledParents = ParentList.size();
|
|
|
|
if (NoOfCompiledParents == 0)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add all the uncompiled blocks to the end of the list
|
|
|
|
for (iter = m_ParentSection.begin(); iter != m_ParentSection.end(); iter++)
|
|
|
|
{
|
|
|
|
CCodeSection * Parent = *iter;
|
|
|
|
BLOCK_PARENT BlockParent;
|
|
|
|
|
|
|
|
if (Parent->m_CompiledLocation != NULL) { continue; }
|
|
|
|
if (Parent->m_JumpSection != Parent->m_ContinueSection)
|
|
|
|
{
|
|
|
|
BlockParent.Parent = Parent;
|
|
|
|
BlockParent.JumpInfo = this == Parent->m_ContinueSection ? &Parent->m_Cont : &Parent->m_Jump;
|
|
|
|
ParentList.push_back(BlockParent);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BlockParent.Parent = Parent;
|
|
|
|
BlockParent.JumpInfo = &Parent->m_Cont;
|
|
|
|
ParentList.push_back(BlockParent);
|
|
|
|
BlockParent.Parent = Parent;
|
|
|
|
BlockParent.JumpInfo = &Parent->m_Jump;
|
|
|
|
ParentList.push_back(BlockParent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int FirstParent = -1;
|
|
|
|
for (size_t i = 0; i < NoOfCompiledParents; i++)
|
|
|
|
{
|
|
|
|
if (!ParentList[i].JumpInfo->FallThrough)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (FirstParent != -1)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
FirstParent = i;
|
|
|
|
}
|
|
|
|
if (FirstParent == -1)
|
|
|
|
{
|
|
|
|
FirstParent = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Link First Parent to start
|
|
|
|
CCodeSection * Parent = ParentList[FirstParent].Parent;
|
|
|
|
CJumpInfo * JumpInfo = ParentList[FirstParent].JumpInfo;
|
|
|
|
|
|
|
|
m_RegWorkingSet = JumpInfo->RegSet;
|
|
|
|
m_RegWorkingSet.ResetX86Protection();
|
|
|
|
|
|
|
|
if (JumpInfo->LinkLocation != NULL)
|
|
|
|
{
|
|
|
|
CPU_Message(" Section_%d (from %d):", m_SectionID, Parent->m_SectionID);
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo->LinkLocation, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo->LinkLocation = NULL;
|
|
|
|
if (JumpInfo->LinkLocation2 != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo->LinkLocation2, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo->LinkLocation2 = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (JumpInfo->ExitReason == CExitInfo::Normal_NoSysCheck)
|
|
|
|
{
|
|
|
|
if (JumpInfo->RegSet.GetBlockCycleCount() != 0)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
if (JumpInfo->JumpPC != (uint32_t)-1)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UpdateCounters(m_RegWorkingSet, m_EnterPC < JumpInfo->JumpPC, true);
|
|
|
|
if (JumpInfo->JumpPC == (uint32_t)-1)
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
if (m_EnterPC <= JumpInfo->JumpPC)
|
|
|
|
{
|
|
|
|
CPU_Message("CompileSystemCheck 10");
|
|
|
|
CompileSystemCheck(m_EnterPC, m_RegWorkingSet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
JumpInfo->FallThrough = false;
|
|
|
|
|
|
|
|
//Fix up initial state
|
|
|
|
UnMap_AllFPRs();
|
|
|
|
|
|
|
|
//determine loop reg usage
|
|
|
|
if (m_InLoop && ParentList.size() > 1)
|
|
|
|
{
|
|
|
|
if (!SetupRegisterForLoop()) { return false; }
|
|
|
|
m_RegWorkingSet.SetRoundingModel(CRegInfo::RoundUnknown);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ParentList.size(); i++)
|
|
|
|
{
|
|
|
|
x86Reg MemoryStackPos;
|
|
|
|
int i2;
|
|
|
|
|
|
|
|
if (i == (size_t)FirstParent) { continue; }
|
|
|
|
Parent = ParentList[i].Parent;
|
|
|
|
if (Parent->m_CompiledLocation == NULL)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
CRegInfo * RegSet = &ParentList[i].JumpInfo->RegSet;
|
|
|
|
|
|
|
|
if (m_RegWorkingSet.GetRoundingModel() != RegSet->GetRoundingModel()) { m_RegWorkingSet.SetRoundingModel(CRegInfo::RoundUnknown); }
|
|
|
|
|
|
|
|
//Find Parent MapRegState
|
|
|
|
MemoryStackPos = x86_Unknown;
|
|
|
|
for (i2 = 0; i2 < sizeof(x86_Registers) / sizeof(x86_Registers[0]); i2++)
|
|
|
|
{
|
|
|
|
if (RegSet->GetX86Mapped(x86_Registers[i2]) == CRegInfo::Stack_Mapped)
|
|
|
|
{
|
|
|
|
MemoryStackPos = x86_Registers[i2];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (MemoryStackPos == x86_Unknown)
|
|
|
|
{
|
|
|
|
// if the memory stack position is not mapped then unmap it
|
|
|
|
x86Reg MemStackReg = Get_MemoryStack();
|
|
|
|
if (MemStackReg != x86_Unknown)
|
|
|
|
{
|
|
|
|
UnMap_X86reg(MemStackReg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i2 = 1; i2 < 32; i2++)
|
|
|
|
{
|
|
|
|
if (Is32BitMapped(i2))
|
|
|
|
{
|
|
|
|
switch (RegSet->GetMipsRegState(i2))
|
|
|
|
{
|
|
|
|
case CRegInfo::STATE_MAPPED_64: Map_GPR_64bit(i2, i2); break;
|
|
|
|
case CRegInfo::STATE_MAPPED_32_ZERO: break;
|
|
|
|
case CRegInfo::STATE_MAPPED_32_SIGN:
|
|
|
|
if (IsUnsigned(i2))
|
|
|
|
{
|
|
|
|
m_RegWorkingSet.SetMipsRegState(i2, CRegInfo::STATE_MAPPED_32_SIGN);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_CONST_64: Map_GPR_64bit(i2, i2); break;
|
|
|
|
case CRegInfo::STATE_CONST_32_SIGN:
|
|
|
|
if ((RegSet->GetMipsRegLo_S(i2) < 0) && IsUnsigned(i2))
|
|
|
|
{
|
|
|
|
m_RegWorkingSet.SetMipsRegState(i2, CRegInfo::STATE_MAPPED_32_SIGN);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_UNKNOWN:
|
|
|
|
if (g_System->b32BitCore())
|
|
|
|
{
|
|
|
|
Map_GPR_32bit(i2, true, i2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//Map_GPR_32bit(i2,true,i2);
|
|
|
|
Map_GPR_64bit(i2, i2); //??
|
|
|
|
//UnMap_GPR(Section,i2,true); ??
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
CPU_Message("Unknown CPU State(%d) in InheritParentInfo", GetMipsRegState(i2));
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (IsConst(i2)) {
|
|
|
|
if (GetMipsRegState(i2) != RegSet->GetMipsRegState(i2))
|
|
|
|
{
|
|
|
|
switch (RegSet->GetMipsRegState(i2))
|
|
|
|
{
|
|
|
|
case CRegInfo::STATE_MAPPED_64:
|
|
|
|
Map_GPR_64bit(i2, i2);
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_MAPPED_32_ZERO:
|
|
|
|
if (Is32Bit(i2))
|
|
|
|
{
|
|
|
|
Map_GPR_32bit(i2, (GetMipsRegLo(i2) & 0x80000000) != 0, i2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_MAPPED_32_SIGN:
|
|
|
|
if (Is32Bit(i2))
|
|
|
|
{
|
|
|
|
Map_GPR_32bit(i2, true, i2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_UNKNOWN:
|
|
|
|
if (g_System->b32BitCore())
|
|
|
|
{
|
|
|
|
Map_GPR_32bit(i2, true, i2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Map_GPR_64bit(i2, i2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
CPU_Message("Unknown CPU State(%d) in InheritParentInfo", RegSet->GetMipsRegState(i2));
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (Is32Bit(i2) && GetMipsRegLo(i2) != RegSet->GetMipsRegLo(i2))
|
|
|
|
{
|
|
|
|
Map_GPR_32bit(i2, true, i2);
|
|
|
|
}
|
|
|
|
else if (Is64Bit(i2) && GetMipsReg(i2) != RegSet->GetMipsReg(i2))
|
|
|
|
{
|
|
|
|
Map_GPR_32bit(i2, true, i2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ResetX86Protection();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MemoryStackPos > 0)
|
|
|
|
{
|
|
|
|
Map_MemoryStack(MemoryStackPos, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_RegEnter = m_RegWorkingSet;
|
|
|
|
|
|
|
|
//Sync registers for different blocks
|
|
|
|
stdstr_f Label("Section_%d", m_SectionID);
|
|
|
|
int CurrentParent = FirstParent;
|
|
|
|
bool NeedSync = false;
|
|
|
|
for (size_t i = 0; i < NoOfCompiledParents; i++)
|
|
|
|
{
|
|
|
|
CRegInfo * RegSet;
|
|
|
|
int i2;
|
|
|
|
|
|
|
|
if (i == (size_t)FirstParent) { continue; }
|
|
|
|
Parent = ParentList[i].Parent;
|
|
|
|
JumpInfo = ParentList[i].JumpInfo;
|
|
|
|
RegSet = &ParentList[i].JumpInfo->RegSet;
|
|
|
|
|
|
|
|
if (JumpInfo->RegSet.GetBlockCycleCount() != 0) { NeedSync = true; }
|
|
|
|
|
|
|
|
for (i2 = 0; !NeedSync && i2 < 8; i2++)
|
|
|
|
{
|
|
|
|
if (m_RegWorkingSet.FpuMappedTo(i2) == (uint32_t)-1)
|
|
|
|
{
|
|
|
|
NeedSync = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i2 = 0; !NeedSync && i2 < sizeof(x86_Registers) / sizeof(x86_Registers[0]); i2++)
|
|
|
|
{
|
|
|
|
if (m_RegWorkingSet.GetX86Mapped(x86_Registers[i2]) == CRegInfo::Stack_Mapped)
|
|
|
|
{
|
|
|
|
if (m_RegWorkingSet.GetX86Mapped(x86_Registers[i2]) != RegSet->GetX86Mapped(x86_Registers[i2]))
|
|
|
|
{
|
|
|
|
NeedSync = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i2 = 0; !NeedSync && i2 < 32; i2++)
|
|
|
|
{
|
|
|
|
if (NeedSync == true) { break; }
|
|
|
|
if (m_RegWorkingSet.GetMipsRegState(i2) != RegSet->GetMipsRegState(i2))
|
|
|
|
{
|
|
|
|
NeedSync = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
switch (m_RegWorkingSet.GetMipsRegState(i2))
|
|
|
|
{
|
|
|
|
case CRegInfo::STATE_UNKNOWN: break;
|
|
|
|
case CRegInfo::STATE_MAPPED_64:
|
|
|
|
if (GetMipsRegMapHi(i2) != RegSet->GetMipsRegMapHi(i2) ||
|
|
|
|
GetMipsRegMapLo(i2) != RegSet->GetMipsRegMapLo(i2))
|
|
|
|
{
|
|
|
|
NeedSync = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_MAPPED_32_ZERO:
|
|
|
|
case CRegInfo::STATE_MAPPED_32_SIGN:
|
|
|
|
if (GetMipsRegMapLo(i2) != RegSet->GetMipsRegMapLo(i2))
|
|
|
|
{
|
|
|
|
//DisplayError(L"Parent: %d",Parent->SectionID);
|
|
|
|
NeedSync = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CRegInfo::STATE_CONST_32_SIGN:
|
|
|
|
if (GetMipsRegLo(i2) != RegSet->GetMipsRegLo(i2))
|
|
|
|
{
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
NeedSync = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2015-12-14 10:51:33 +00:00
|
|
|
WriteTrace(TraceRecompiler, TraceError, "Unhandled Reg state %d\nin InheritParentInfo", GetMipsRegState(i2));
|
2015-12-09 11:37:58 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (NeedSync == false) { continue; }
|
|
|
|
Parent = ParentList[CurrentParent].Parent;
|
|
|
|
JumpInfo = ParentList[CurrentParent].JumpInfo;
|
|
|
|
JmpLabel32(Label.c_str(), 0);
|
2016-06-28 11:22:30 +00:00
|
|
|
JumpInfo->LinkLocation = (uint32_t *)(*g_RecompPos - 4);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo->LinkLocation2 = NULL;
|
|
|
|
|
|
|
|
CurrentParent = i;
|
|
|
|
Parent = ParentList[CurrentParent].Parent;
|
|
|
|
JumpInfo = ParentList[CurrentParent].JumpInfo;
|
|
|
|
CPU_Message(" Section_%d (from %d):", m_SectionID, Parent->m_SectionID);
|
|
|
|
if (JumpInfo->LinkLocation != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo->LinkLocation, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo->LinkLocation = NULL;
|
|
|
|
if (JumpInfo->LinkLocation2 != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo->LinkLocation2, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo->LinkLocation2 = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//if (m_EnterPC == 0x8031CE44 && m_SectionID == 6)
|
|
|
|
//{
|
2015-12-09 11:37:58 +00:00
|
|
|
// g_Notify->BreakPoint(__FILE__, __LINE__);
|
2015-11-15 02:27:06 +00:00
|
|
|
//}
|
|
|
|
m_RegWorkingSet = JumpInfo->RegSet;
|
|
|
|
if (m_EnterPC < JumpInfo->JumpPC)
|
|
|
|
{
|
|
|
|
UpdateCounters(m_RegWorkingSet, true, true);
|
|
|
|
CPU_Message("CompileSystemCheck 11");
|
|
|
|
CompileSystemCheck(m_EnterPC, m_RegWorkingSet);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
|
|
}
|
|
|
|
SyncRegState(m_RegEnter); //Sync
|
|
|
|
m_RegEnter = m_RegWorkingSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < NoOfCompiledParents; i++)
|
|
|
|
{
|
|
|
|
Parent = ParentList[i].Parent;
|
|
|
|
JumpInfo = ParentList[i].JumpInfo;
|
|
|
|
|
|
|
|
if (JumpInfo->LinkLocation != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo->LinkLocation, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo->LinkLocation = NULL;
|
|
|
|
if (JumpInfo->LinkLocation2 != NULL)
|
|
|
|
{
|
2016-06-28 11:22:30 +00:00
|
|
|
SetJump32(JumpInfo->LinkLocation2, (uint32_t *)*g_RecompPos);
|
2015-11-15 02:27:06 +00:00
|
|
|
JumpInfo->LinkLocation2 = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CPU_Message(" Section_%d:", m_SectionID);
|
|
|
|
m_RegWorkingSet.SetBlockCycleCount(0);
|
|
|
|
return true;
|
2010-10-23 18:53:01 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 06:55:16 +00:00
|
|
|
bool CCodeSection::DisplaySectionInformation(uint32_t ID, uint32_t Test)
|
2010-10-23 18:53:01 +00:00
|
|
|
{
|
2016-06-27 07:26:35 +00:00
|
|
|
if (!g_bRecompilerLogging)
|
2015-11-15 02:27:06 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (this == NULL) { return false; }
|
|
|
|
if (m_Test == Test) { return false; }
|
|
|
|
m_Test = Test;
|
|
|
|
if (m_SectionID != ID)
|
|
|
|
{
|
|
|
|
if (m_ContinueSection->DisplaySectionInformation(ID, Test)) { return true; }
|
|
|
|
if (m_JumpSection->DisplaySectionInformation(ID, Test)) { return true; }
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
DisplaySectionInformation();
|
|
|
|
return true;
|
2010-11-12 05:30:08 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 22:19:02 +00:00
|
|
|
void CCodeSection::DisplaySectionInformation()
|
2010-11-12 05:30:08 +00:00
|
|
|
{
|
2015-11-15 02:27:06 +00:00
|
|
|
if (m_SectionID == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CPU_Message("====== Section %d ======", m_SectionID);
|
|
|
|
CPU_Message("Start PC: %X", m_EnterPC);
|
2016-06-27 07:26:35 +00:00
|
|
|
if (g_System->bLinkBlocks())
|
|
|
|
{
|
|
|
|
CPU_Message("End PC: %X", m_EndPC);
|
|
|
|
}
|
2015-11-15 02:27:06 +00:00
|
|
|
CPU_Message("CompiledLocation: %X", m_CompiledLocation);
|
2016-06-27 07:26:35 +00:00
|
|
|
if (g_System->bLinkBlocks() && !m_ParentSection.empty())
|
2015-11-15 02:27:06 +00:00
|
|
|
{
|
|
|
|
stdstr ParentList;
|
|
|
|
for (SECTION_LIST::iterator iter = m_ParentSection.begin(); iter != m_ParentSection.end(); iter++)
|
|
|
|
{
|
|
|
|
CCodeSection * Parent = *iter;
|
|
|
|
if (!ParentList.empty())
|
|
|
|
{
|
|
|
|
ParentList += ", ";
|
|
|
|
}
|
|
|
|
ParentList += stdstr_f("%d", Parent->m_SectionID);
|
|
|
|
}
|
|
|
|
CPU_Message("Number of parents: %d (%s)", m_ParentSection.size(), ParentList.c_str());
|
|
|
|
}
|
|
|
|
|
2016-06-27 07:26:35 +00:00
|
|
|
if (g_System->bLinkBlocks())
|
2015-11-15 02:27:06 +00:00
|
|
|
{
|
2016-06-27 07:26:35 +00:00
|
|
|
CPU_Message("Jump Address: 0x%08X", m_Jump.JumpPC);
|
|
|
|
CPU_Message("Jump Target Address: 0x%08X", m_Jump.TargetPC);
|
|
|
|
if (m_JumpSection != NULL)
|
|
|
|
{
|
|
|
|
CPU_Message("Jump Section: %d", m_JumpSection->m_SectionID);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CPU_Message("Jump Section: None");
|
|
|
|
}
|
|
|
|
CPU_Message("Continue Address: 0x%08X", m_Cont.JumpPC);
|
|
|
|
CPU_Message("Continue Target Address: 0x%08X", m_Cont.TargetPC);
|
|
|
|
if (m_ContinueSection != NULL) {
|
|
|
|
CPU_Message("Continue Section: %d", m_ContinueSection->m_SectionID);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CPU_Message("Continue Section: None");
|
|
|
|
}
|
|
|
|
CPU_Message("In Loop: %s", m_InLoop ? "Yes" : "No");
|
2015-11-15 02:27:06 +00:00
|
|
|
}
|
|
|
|
CPU_Message("=======================");
|
2015-11-09 06:55:16 +00:00
|
|
|
}
|