|
|
@ -184,7 +184,7 @@ CX86RecompilerOps::CX86RecompilerOps(CN64System & m_System, CCodeBlock & CodeBlo
|
|
|
|
m_Assembler(CodeBlock),
|
|
|
|
m_Assembler(CodeBlock),
|
|
|
|
m_PipelineStage(PIPELINE_STAGE_NORMAL),
|
|
|
|
m_PipelineStage(PIPELINE_STAGE_NORMAL),
|
|
|
|
m_RegWorkingSet(CodeBlock, m_Assembler),
|
|
|
|
m_RegWorkingSet(CodeBlock, m_Assembler),
|
|
|
|
m_CompilePC(m_Instruction.Address()),
|
|
|
|
m_CompilePC(m_Instruction.Address32()),
|
|
|
|
m_RegBeforeDelay(CodeBlock, m_Assembler),
|
|
|
|
m_RegBeforeDelay(CodeBlock, m_Assembler),
|
|
|
|
m_EffectDelaySlot(false)
|
|
|
|
m_EffectDelaySlot(false)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -2325,7 +2325,7 @@ void CX86RecompilerOps::JAL()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
UpdateCounters(m_RegWorkingSet, bCheck, true);
|
|
|
|
UpdateCounters(m_RegWorkingSet, bCheck, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CompileExit((uint64_t)-1, (uint64_t)-1, m_RegWorkingSet, bCheck ? ExitReason_Normal : ExitReason_NormalNoSysCheck, true, nullptr);
|
|
|
|
CompileExit((uint32_t)-1, (uint32_t)-1, m_RegWorkingSet, bCheck ? ExitReason_Normal : ExitReason_NormalNoSysCheck, true, nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
|
|
|
|
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -4520,7 +4520,7 @@ void CX86RecompilerOps::SPECIAL_JR()
|
|
|
|
R4300iOpcode DelaySlot;
|
|
|
|
R4300iOpcode DelaySlot;
|
|
|
|
if (g_MMU->MemoryValue32((uint32_t)(m_CompilePC + 4), DelaySlot.Value) && R4300iInstruction(m_CompilePC, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
|
|
|
|
if (g_MMU->MemoryValue32((uint32_t)(m_CompilePC + 4), DelaySlot.Value) && R4300iInstruction(m_CompilePC, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
CompileExit(m_CompilePC, (uint64_t)-1, m_RegWorkingSet, ExitReason_CheckPCAlignment, true, nullptr);
|
|
|
|
CompileExit(m_CompilePC, (uint32_t)-1, m_RegWorkingSet, ExitReason_CheckPCAlignment, true, nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -4537,7 +4537,7 @@ void CX86RecompilerOps::SPECIAL_JR()
|
|
|
|
m_Assembler.MoveX86regToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, m_Opcode.rs, false, false));
|
|
|
|
m_Assembler.MoveX86regToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, m_Opcode.rs, false, false));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
UpdateCounters(m_RegWorkingSet, true, true, false);
|
|
|
|
UpdateCounters(m_RegWorkingSet, true, true, false);
|
|
|
|
CompileExit((uint64_t)-1, (uint64_t)-1, m_RegWorkingSet, ExitReason_CheckPCAlignment, true, nullptr);
|
|
|
|
CompileExit((uint32_t)-1, (uint32_t)-1, m_RegWorkingSet, ExitReason_CheckPCAlignment, true, nullptr);
|
|
|
|
if (m_Section->m_JumpSection)
|
|
|
|
if (m_Section->m_JumpSection)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_Section->GenerateSectionLinkage();
|
|
|
|
m_Section->GenerateSectionLinkage();
|
|
|
@ -4606,7 +4606,7 @@ void CX86RecompilerOps::SPECIAL_JALR()
|
|
|
|
if (g_MMU->MemoryValue32((uint32_t)(m_CompilePC + 4), DelaySlot.Value) &&
|
|
|
|
if (g_MMU->MemoryValue32((uint32_t)(m_CompilePC + 4), DelaySlot.Value) &&
|
|
|
|
R4300iInstruction(m_CompilePC, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
|
|
|
|
R4300iInstruction(m_CompilePC, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
CompileExit(m_CompilePC, (uint64_t)-1, m_RegWorkingSet, ExitReason_CheckPCAlignment, true, nullptr);
|
|
|
|
CompileExit(m_CompilePC, (uint32_t)-1, m_RegWorkingSet, ExitReason_CheckPCAlignment, true, nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -4623,7 +4623,7 @@ void CX86RecompilerOps::SPECIAL_JALR()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_Assembler.MoveX86regToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, m_Opcode.rs, false, false));
|
|
|
|
m_Assembler.MoveX86regToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_RegWorkingSet.Map_TempReg(x86Reg_Unknown, m_Opcode.rs, false, false));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CompileExit((uint64_t)-1, (uint64_t)-1, m_RegWorkingSet, ExitReason_CheckPCAlignment, true, nullptr);
|
|
|
|
CompileExit((uint32_t)-1, (uint32_t)-1, m_RegWorkingSet, ExitReason_CheckPCAlignment, true, nullptr);
|
|
|
|
if (m_Section->m_JumpSection)
|
|
|
|
if (m_Section->m_JumpSection)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_Section->GenerateSectionLinkage();
|
|
|
|
m_Section->GenerateSectionLinkage();
|
|
|
@ -7484,7 +7484,7 @@ void CX86RecompilerOps::COP0_CO_ERET(void)
|
|
|
|
m_Assembler.CallFunc((uint32_t)x86_compiler_COP0_CO_ERET, "x86_compiler_COP0_CO_ERET");
|
|
|
|
m_Assembler.CallFunc((uint32_t)x86_compiler_COP0_CO_ERET, "x86_compiler_COP0_CO_ERET");
|
|
|
|
|
|
|
|
|
|
|
|
UpdateCounters(m_RegWorkingSet, true, true);
|
|
|
|
UpdateCounters(m_RegWorkingSet, true, true);
|
|
|
|
CompileExit(m_CompilePC, (uint64_t)-1, m_RegWorkingSet, ExitReason_Normal, true, nullptr);
|
|
|
|
CompileExit(m_CompilePC, (uint32_t)-1, m_RegWorkingSet, ExitReason_Normal, true, nullptr);
|
|
|
|
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
|
|
|
|
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -7811,7 +7811,7 @@ void CX86RecompilerOps::COP1_S_CMP()
|
|
|
|
m_Assembler.test(StatusReg, FPCSR_EV);
|
|
|
|
m_Assembler.test(StatusReg, FPCSR_EV);
|
|
|
|
CRegInfo ExitRegSet = m_RegWorkingSet;
|
|
|
|
CRegInfo ExitRegSet = m_RegWorkingSet;
|
|
|
|
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
CompileExit((uint64_t)-1, (uint64_t)-1, ExitRegSet, ExitReason_ExceptionFloatingPoint, false, &CX86Ops::JnzLabel);
|
|
|
|
CompileExit((uint32_t)-1, (uint32_t)-1, ExitRegSet, ExitReason_ExceptionFloatingPoint, false, &CX86Ops::JnzLabel);
|
|
|
|
m_Assembler.or_(StatusReg, (uint32_t)FPCSR_FV);
|
|
|
|
m_Assembler.or_(StatusReg, (uint32_t)FPCSR_FV);
|
|
|
|
if ((m_Opcode.funct & 8) == 0)
|
|
|
|
if ((m_Opcode.funct & 8) == 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -8005,7 +8005,7 @@ void CX86RecompilerOps::COP1_D_CMP()
|
|
|
|
m_Assembler.test(StatusReg, FPCSR_EV);
|
|
|
|
m_Assembler.test(StatusReg, FPCSR_EV);
|
|
|
|
CRegInfo ExitRegSet = m_RegWorkingSet;
|
|
|
|
CRegInfo ExitRegSet = m_RegWorkingSet;
|
|
|
|
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
CompileExit((uint64_t)-1, (uint64_t)-1, ExitRegSet, ExitReason_ExceptionFloatingPoint, false, &CX86Ops::JnzLabel);
|
|
|
|
CompileExit((uint32_t)-1, (uint32_t)-1, ExitRegSet, ExitReason_ExceptionFloatingPoint, false, &CX86Ops::JnzLabel);
|
|
|
|
m_Assembler.or_(StatusReg, (uint32_t)FPCSR_FV);
|
|
|
|
m_Assembler.or_(StatusReg, (uint32_t)FPCSR_FV);
|
|
|
|
if ((m_Opcode.funct & 8) == 0)
|
|
|
|
if ((m_Opcode.funct & 8) == 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -8070,7 +8070,7 @@ void CX86RecompilerOps::UnknownOpcode()
|
|
|
|
|
|
|
|
|
|
|
|
m_RegWorkingSet.WriteBackRegisters();
|
|
|
|
m_RegWorkingSet.WriteBackRegisters();
|
|
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
|
|
m_Assembler.MoveConst64ToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.MoveConstToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
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);
|
|
|
@ -8128,7 +8128,7 @@ void CX86RecompilerOps::ClearCachedInstructionInfo()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_RegWorkingSet.WriteBackRegisters();
|
|
|
|
m_RegWorkingSet.WriteBackRegisters();
|
|
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
|
|
m_Assembler.MoveConst64ToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.MoveConstToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
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);
|
|
|
@ -8231,7 +8231,7 @@ void CX86RecompilerOps::CompileExitCode()
|
|
|
|
m_CodeBlock.Log("");
|
|
|
|
m_CodeBlock.Log("");
|
|
|
|
m_Assembler.bind(ExitIter->JumpLabel);
|
|
|
|
m_Assembler.bind(ExitIter->JumpLabel);
|
|
|
|
m_PipelineStage = ExitIter->PipelineStage;
|
|
|
|
m_PipelineStage = ExitIter->PipelineStage;
|
|
|
|
CompileExit((uint64_t)-1, ExitIter->TargetPC, ExitIter->ExitRegSet, ExitIter->Reason, true, nullptr);
|
|
|
|
CompileExit((uint32_t)-1, ExitIter->TargetPC, ExitIter->ExitRegSet, ExitIter->Reason, true, nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -8337,7 +8337,7 @@ void CX86RecompilerOps::CompileCheckFPUInput(asmjit::x86::Gp RegPointer, FpuOpSi
|
|
|
|
{
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_Assembler.MoveConst64ToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.MoveConstToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
if (OpSize == FpuOpSize_32bit)
|
|
|
|
if (OpSize == FpuOpSize_32bit)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_Assembler.PushImm32("m_TempValue32", (uint32_t)&m_TempValue32);
|
|
|
|
m_Assembler.PushImm32("m_TempValue32", (uint32_t)&m_TempValue32);
|
|
|
@ -8366,7 +8366,7 @@ void CX86RecompilerOps::CompileCheckFPUInput(asmjit::x86::Gp RegPointer, FpuOpSi
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
CRegInfo ExitRegSet = m_RegWorkingSet;
|
|
|
|
CRegInfo ExitRegSet = m_RegWorkingSet;
|
|
|
|
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
CompileExit((uint64_t)-1, (uint64_t)-1, ExitRegSet, ExitReason_Exception, false, &CX86Ops::JnzLabel);
|
|
|
|
CompileExit((uint32_t)-1, (uint32_t)-1, ExitRegSet, ExitReason_Exception, false, &CX86Ops::JnzLabel);
|
|
|
|
m_Assembler.bind(ValidFpuValue);
|
|
|
|
m_Assembler.bind(ValidFpuValue);
|
|
|
|
if (m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT)
|
|
|
|
if (m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -8402,14 +8402,14 @@ void CX86RecompilerOps::CompileCheckFPUResult32(int32_t DestReg)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_Assembler.MoveConst64ToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.MoveConstToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.PushImm32("Result", (uint32_t)&m_TempValue32);
|
|
|
|
m_Assembler.PushImm32("Result", (uint32_t)&m_TempValue32);
|
|
|
|
m_Assembler.CallThis((uint32_t)&g_System->m_OpCodes, AddressOf(&R4300iOp::CheckFPUResult32), "R4300iOp::CheckFPUResult32", 8);
|
|
|
|
m_Assembler.CallThis((uint32_t)&g_System->m_OpCodes, AddressOf(&R4300iOp::CheckFPUResult32), "R4300iOp::CheckFPUResult32", 8);
|
|
|
|
m_Assembler.test(asmjit::x86::al, asmjit::x86::al);
|
|
|
|
m_Assembler.test(asmjit::x86::al, asmjit::x86::al);
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
CRegInfo ExitRegSet = m_RegWorkingSet;
|
|
|
|
CRegInfo ExitRegSet = m_RegWorkingSet;
|
|
|
|
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
CompileExit((uint64_t)-1, (uint64_t)-1, ExitRegSet, ExitReason_Exception, false, &CX86Ops::JneLabel);
|
|
|
|
CompileExit((uint32_t)-1, (uint32_t)-1, ExitRegSet, ExitReason_Exception, false, &CX86Ops::JneLabel);
|
|
|
|
if (m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT)
|
|
|
|
if (m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", PIPELINE_STAGE_NORMAL);
|
|
|
|
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", PIPELINE_STAGE_NORMAL);
|
|
|
@ -8482,14 +8482,14 @@ void CX86RecompilerOps::CompileCheckFPUResult64(asmjit::x86::Gp RegPointer)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_Assembler.MoveConst64ToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.MoveConstToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.push(RegPointer);
|
|
|
|
m_Assembler.push(RegPointer);
|
|
|
|
m_Assembler.CallThis((uint32_t)&g_System->m_OpCodes, AddressOf(&R4300iOp::CheckFPUResult64), "R4300iOp::CheckFPUResult64", 8);
|
|
|
|
m_Assembler.CallThis((uint32_t)&g_System->m_OpCodes, AddressOf(&R4300iOp::CheckFPUResult64), "R4300iOp::CheckFPUResult64", 8);
|
|
|
|
m_Assembler.test(asmjit::x86::al, asmjit::x86::al);
|
|
|
|
m_Assembler.test(asmjit::x86::al, asmjit::x86::al);
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
CRegInfo ExitRegSet = m_RegWorkingSet;
|
|
|
|
CRegInfo ExitRegSet = m_RegWorkingSet;
|
|
|
|
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
CompileExit((uint64_t)-1, (uint64_t)-1, ExitRegSet, ExitReason_Exception, false, &CX86Ops::JneLabel);
|
|
|
|
CompileExit((uint32_t)-1, (uint32_t)-1, ExitRegSet, ExitReason_Exception, false, &CX86Ops::JneLabel);
|
|
|
|
if (m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT)
|
|
|
|
if (m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", PIPELINE_STAGE_NORMAL);
|
|
|
|
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", PIPELINE_STAGE_NORMAL);
|
|
|
@ -9309,7 +9309,7 @@ void CX86RecompilerOps::SetCurrentPC(uint32_t ProgramCounter)
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t CX86RecompilerOps::GetCurrentPC(void)
|
|
|
|
uint32_t CX86RecompilerOps::GetCurrentPC(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return (uint32_t)m_CompilePC;
|
|
|
|
return m_CompilePC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CX86RecompilerOps::SetCurrentSection(CCodeSection * section)
|
|
|
|
void CX86RecompilerOps::SetCurrentSection(CCodeSection * section)
|
|
|
@ -9418,7 +9418,7 @@ void CX86RecompilerOps::CompileExecuteBP(void)
|
|
|
|
m_RegWorkingSet.WriteBackRegisters();
|
|
|
|
m_RegWorkingSet.WriteBackRegisters();
|
|
|
|
|
|
|
|
|
|
|
|
UpdateCounters(m_RegWorkingSet, true, true);
|
|
|
|
UpdateCounters(m_RegWorkingSet, true, true);
|
|
|
|
m_Assembler.MoveConst64ToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.MoveConstToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
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);
|
|
|
@ -9438,7 +9438,7 @@ void CX86RecompilerOps::CompileExecuteDelaySlotBP(void)
|
|
|
|
m_RegWorkingSet.WriteBackRegisters();
|
|
|
|
m_RegWorkingSet.WriteBackRegisters();
|
|
|
|
|
|
|
|
|
|
|
|
UpdateCounters(m_RegWorkingSet, true, true);
|
|
|
|
UpdateCounters(m_RegWorkingSet, true, true);
|
|
|
|
m_Assembler.MoveConst64ToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.MoveConstToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
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);
|
|
|
@ -9462,7 +9462,7 @@ void CX86RecompilerOps::OverflowDelaySlot(bool TestTimer)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_Assembler.MoveConst64ToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC + 4);
|
|
|
|
m_Assembler.MoveConstToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC + 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 (g_SyncSystem)
|
|
|
|
if (g_SyncSystem)
|
|
|
@ -9491,12 +9491,12 @@ void CX86RecompilerOps::OverflowDelaySlot(bool TestTimer)
|
|
|
|
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
|
|
|
|
m_PipelineStage = PIPELINE_STAGE_END_BLOCK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CX86RecompilerOps::CompileExit(uint64_t JumpPC, uint64_t TargetPC, CRegInfo & ExitRegSet, ExitReason reason)
|
|
|
|
void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo & ExitRegSet, ExitReason reason)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
CompileExit(JumpPC, TargetPC, ExitRegSet, reason, true, nullptr);
|
|
|
|
CompileExit(JumpPC, TargetPC, ExitRegSet, reason, true, nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CX86RecompilerOps::CompileExit(uint64_t JumpPC, uint64_t TargetPC, CRegInfo & ExitRegSet, ExitReason reason, bool CompileNow, void (CX86Ops::*x86Jmp)(const char * LabelName, asmjit::Label & JumpLabel))
|
|
|
|
void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo & ExitRegSet, ExitReason reason, bool CompileNow, void (CX86Ops::*x86Jmp)(const char * LabelName, asmjit::Label & JumpLabel))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!CompileNow)
|
|
|
|
if (!CompileNow)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -9521,10 +9521,10 @@ void CX86RecompilerOps::CompileExit(uint64_t JumpPC, uint64_t TargetPC, CRegInfo
|
|
|
|
//m_CodeBlock.Log("CompileExit: %d",reason);
|
|
|
|
//m_CodeBlock.Log("CompileExit: %d",reason);
|
|
|
|
ExitRegSet.WriteBackRegisters();
|
|
|
|
ExitRegSet.WriteBackRegisters();
|
|
|
|
|
|
|
|
|
|
|
|
if (TargetPC != (uint64_t)-1)
|
|
|
|
if (TargetPC != (uint32_t)-1)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_Assembler.MoveConst64ToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", TargetPC);
|
|
|
|
m_Assembler.MoveConstToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", TargetPC);
|
|
|
|
UpdateCounters(ExitRegSet, TargetPC <= JumpPC && JumpPC != (uint64_t)-1, reason == ExitReason_Normal);
|
|
|
|
UpdateCounters(ExitRegSet, TargetPC <= JumpPC && JumpPC != (uint32_t)-1, reason == ExitReason_Normal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -9538,7 +9538,7 @@ void CX86RecompilerOps::CompileExit(uint64_t JumpPC, uint64_t TargetPC, CRegInfo
|
|
|
|
case ExitReason_CheckPCAlignment:
|
|
|
|
case ExitReason_CheckPCAlignment:
|
|
|
|
case ExitReason_NormalNoSysCheck:
|
|
|
|
case ExitReason_NormalNoSysCheck:
|
|
|
|
ExitRegSet.SetBlockCycleCount(0);
|
|
|
|
ExitRegSet.SetBlockCycleCount(0);
|
|
|
|
if ((reason == ExitReason_Normal || reason == ExitReason_CheckPCAlignment) && (TargetPC == (uint64_t)-1 || TargetPC <= JumpPC))
|
|
|
|
if ((reason == ExitReason_Normal || reason == ExitReason_CheckPCAlignment) && (TargetPC == (uint32_t)-1 || TargetPC <= JumpPC))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
CompileSystemCheck((uint32_t)-1, ExitRegSet);
|
|
|
|
CompileSystemCheck((uint32_t)-1, ExitRegSet);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -9837,7 +9837,7 @@ void CX86RecompilerOps::CompileLoadMemoryValue(asmjit::x86::Gp & AddressReg, con
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_Assembler.SubConstFromVariable(OpsExecuted, g_NextTimer, "g_NextTimer");
|
|
|
|
m_Assembler.SubConstFromVariable(OpsExecuted, g_NextTimer, "g_NextTimer");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_Assembler.MoveConst64ToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.MoveConstToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
if (m_PipelineStage != PIPELINE_STAGE_NORMAL)
|
|
|
|
if (m_PipelineStage != PIPELINE_STAGE_NORMAL)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", PIPELINE_STAGE_JUMP);
|
|
|
|
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", PIPELINE_STAGE_JUMP);
|
|
|
@ -9850,7 +9850,7 @@ void CX86RecompilerOps::CompileLoadMemoryValue(asmjit::x86::Gp & AddressReg, con
|
|
|
|
m_Assembler.CallThis((uint32_t)(&m_MMU), AddressOf(&CMipsMemoryVM::LW_VAddr32), "CMipsMemoryVM::LW_VAddr32", 12);
|
|
|
|
m_Assembler.CallThis((uint32_t)(&m_MMU), AddressOf(&CMipsMemoryVM::LW_VAddr32), "CMipsMemoryVM::LW_VAddr32", 12);
|
|
|
|
m_Assembler.test(asmjit::x86::al, asmjit::x86::al);
|
|
|
|
m_Assembler.test(asmjit::x86::al, asmjit::x86::al);
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
CompileExit((uint64_t)-1, (uint64_t)-1, m_RegWorkingSet, ExitReason_NormalNoSysCheck, false, &CX86Ops::JeLabel);
|
|
|
|
CompileExit((uint32_t)-1, (uint32_t)-1, m_RegWorkingSet, ExitReason_NormalNoSysCheck, false, &CX86Ops::JeLabel);
|
|
|
|
m_Assembler.MoveConstToX86reg(TempReg, (uint32_t)&m_TempValue32);
|
|
|
|
m_Assembler.MoveConstToX86reg(TempReg, (uint32_t)&m_TempValue32);
|
|
|
|
m_Assembler.sub(TempReg, AddressReg);
|
|
|
|
m_Assembler.sub(TempReg, AddressReg);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -9862,7 +9862,7 @@ void CX86RecompilerOps::CompileLoadMemoryValue(asmjit::x86::Gp & AddressReg, con
|
|
|
|
m_Assembler.CallThis((uint32_t)(&m_MMU), AddressOf(&CMipsMemoryVM::LH_VAddr32), "CMipsMemoryVM::LH_VAddr32", 12);
|
|
|
|
m_Assembler.CallThis((uint32_t)(&m_MMU), AddressOf(&CMipsMemoryVM::LH_VAddr32), "CMipsMemoryVM::LH_VAddr32", 12);
|
|
|
|
m_Assembler.test(asmjit::x86::al, asmjit::x86::al);
|
|
|
|
m_Assembler.test(asmjit::x86::al, asmjit::x86::al);
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
CompileExit((uint64_t)-1, (uint64_t)-1, m_RegWorkingSet, ExitReason_NormalNoSysCheck, false, &CX86Ops::JeLabel);
|
|
|
|
CompileExit((uint32_t)-1, (uint32_t)-1, m_RegWorkingSet, ExitReason_NormalNoSysCheck, false, &CX86Ops::JeLabel);
|
|
|
|
m_Assembler.MoveConstToX86reg(TempReg, (uint32_t)&m_TempValue32);
|
|
|
|
m_Assembler.MoveConstToX86reg(TempReg, (uint32_t)&m_TempValue32);
|
|
|
|
m_Assembler.sub(TempReg, AddressReg);
|
|
|
|
m_Assembler.sub(TempReg, AddressReg);
|
|
|
|
m_Assembler.xor_(AddressReg, 2);
|
|
|
|
m_Assembler.xor_(AddressReg, 2);
|
|
|
@ -9875,7 +9875,7 @@ void CX86RecompilerOps::CompileLoadMemoryValue(asmjit::x86::Gp & AddressReg, con
|
|
|
|
m_Assembler.CallThis((uint32_t)&m_MMU, AddressOf(&CMipsMemoryVM::LB_VAddr32), "CMipsMemoryVM::LB_VAddr32", 12);
|
|
|
|
m_Assembler.CallThis((uint32_t)&m_MMU, AddressOf(&CMipsMemoryVM::LB_VAddr32), "CMipsMemoryVM::LB_VAddr32", 12);
|
|
|
|
m_Assembler.test(asmjit::x86::al, asmjit::x86::al);
|
|
|
|
m_Assembler.test(asmjit::x86::al, asmjit::x86::al);
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
CompileExit((uint64_t)-1, (uint64_t)-1, m_RegWorkingSet, ExitReason_NormalNoSysCheck, false, &CX86Ops::JeLabel);
|
|
|
|
CompileExit((uint32_t)-1, (uint32_t)-1, m_RegWorkingSet, ExitReason_NormalNoSysCheck, false, &CX86Ops::JeLabel);
|
|
|
|
m_Assembler.MoveConstToX86reg(TempReg, (uint32_t)&m_TempValue32);
|
|
|
|
m_Assembler.MoveConstToX86reg(TempReg, (uint32_t)&m_TempValue32);
|
|
|
|
m_Assembler.sub(TempReg, AddressReg);
|
|
|
|
m_Assembler.sub(TempReg, AddressReg);
|
|
|
|
m_Assembler.xor_(AddressReg, 3);
|
|
|
|
m_Assembler.xor_(AddressReg, 3);
|
|
|
@ -10044,7 +10044,7 @@ void CX86RecompilerOps::CompileStoreMemoryValue(asmjit::x86::Gp AddressReg, cons
|
|
|
|
asmjit::Label JumpFound = m_Assembler.newLabel();
|
|
|
|
asmjit::Label JumpFound = m_Assembler.newLabel();
|
|
|
|
m_Assembler.JneLabel(stdstr_f("MemoryWriteMap_%X_Found", m_CompilePC).c_str(), JumpFound);
|
|
|
|
m_Assembler.JneLabel(stdstr_f("MemoryWriteMap_%X_Found", m_CompilePC).c_str(), JumpFound);
|
|
|
|
|
|
|
|
|
|
|
|
m_Assembler.MoveConst64ToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.MoveConstToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
if (m_PipelineStage != PIPELINE_STAGE_NORMAL)
|
|
|
|
if (m_PipelineStage != PIPELINE_STAGE_NORMAL)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", m_PipelineStage);
|
|
|
|
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", m_PipelineStage);
|
|
|
@ -11495,13 +11495,13 @@ void CX86RecompilerOps::COP1_S_CVT(CRegBase::FPU_ROUND RoundMethod, CRegInfo::FP
|
|
|
|
{
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_Assembler.MoveConst64ToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.MoveConstToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.CallThis((uint32_t)&g_System->m_OpCodes, AddressOf(&R4300iOp::CheckFPUInvalidException), "R4300iOp::CheckFPUInvalidException", 8);
|
|
|
|
m_Assembler.CallThis((uint32_t)&g_System->m_OpCodes, AddressOf(&R4300iOp::CheckFPUInvalidException), "R4300iOp::CheckFPUInvalidException", 8);
|
|
|
|
m_Assembler.test(asmjit::x86::al, asmjit::x86::al);
|
|
|
|
m_Assembler.test(asmjit::x86::al, asmjit::x86::al);
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
CRegInfo ExitRegSet = m_RegWorkingSet;
|
|
|
|
CRegInfo ExitRegSet = m_RegWorkingSet;
|
|
|
|
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
CompileExit((uint64_t)-1, (uint64_t)-1, ExitRegSet, ExitReason_Exception, false, &CX86Ops::JnzLabel);
|
|
|
|
CompileExit((uint32_t)-1, (uint32_t)-1, ExitRegSet, ExitReason_Exception, false, &CX86Ops::JnzLabel);
|
|
|
|
if (m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT)
|
|
|
|
if (m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", PIPELINE_STAGE_NORMAL);
|
|
|
|
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", PIPELINE_STAGE_NORMAL);
|
|
|
@ -11529,13 +11529,13 @@ void CX86RecompilerOps::COP1_S_CVT(CRegBase::FPU_ROUND RoundMethod, CRegInfo::FP
|
|
|
|
{
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_Assembler.MoveConst64ToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.MoveConstToVariable(&m_Reg.m_PROGRAM_COUNTER, "PROGRAM_COUNTER", m_CompilePC);
|
|
|
|
m_Assembler.CallThis((uint32_t)&g_System->m_OpCodes, AddressOf(&R4300iOp::CheckFPUInvalidException), "R4300iOp::CheckFPUInvalidException", 8);
|
|
|
|
m_Assembler.CallThis((uint32_t)&g_System->m_OpCodes, AddressOf(&R4300iOp::CheckFPUInvalidException), "R4300iOp::CheckFPUInvalidException", 8);
|
|
|
|
m_Assembler.test(asmjit::x86::al, asmjit::x86::al);
|
|
|
|
m_Assembler.test(asmjit::x86::al, asmjit::x86::al);
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
m_RegWorkingSet.AfterCallDirect();
|
|
|
|
CRegInfo ExitRegSet = m_RegWorkingSet;
|
|
|
|
CRegInfo ExitRegSet = m_RegWorkingSet;
|
|
|
|
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
ExitRegSet.SetBlockCycleCount(ExitRegSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
CompileExit((uint64_t)-1, (uint64_t)-1, ExitRegSet, ExitReason_Exception, false, &CX86Ops::JnzLabel);
|
|
|
|
CompileExit((uint32_t)-1, (uint32_t)-1, ExitRegSet, ExitReason_Exception, false, &CX86Ops::JnzLabel);
|
|
|
|
if (m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT)
|
|
|
|
if (m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", PIPELINE_STAGE_NORMAL);
|
|
|
|
m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", PIPELINE_STAGE_NORMAL);
|
|
|
|