Core: Move DelaySlotEffectsCompare into R4300iInstruction

This commit is contained in:
zilmar 2022-07-25 16:35:42 +09:30
parent 0abc7ccaa4
commit 09b535551d
11 changed files with 429 additions and 388 deletions

View File

@ -18,200 +18,6 @@ void ExecuteInterpreterOps(uint32_t /*Cycles*/)
g_Notify->BreakPoint(__FILE__, __LINE__); g_Notify->BreakPoint(__FILE__, __LINE__);
} }
bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2)
{
R4300iOpcode Command;
if (!g_MMU->MemoryValue32(PC + 4, Command.Value))
{
//g_Notify->DisplayError("Failed to load word 2");
//ExitThread(0);
return true;
}
switch (Command.op)
{
case R4300i_SPECIAL:
switch (Command.funct)
{
case R4300i_SPECIAL_SLL:
case R4300i_SPECIAL_SRL:
case R4300i_SPECIAL_SRA:
case R4300i_SPECIAL_SLLV:
case R4300i_SPECIAL_SRLV:
case R4300i_SPECIAL_SRAV:
case R4300i_SPECIAL_MFHI:
case R4300i_SPECIAL_MTHI:
case R4300i_SPECIAL_MFLO:
case R4300i_SPECIAL_MTLO:
case R4300i_SPECIAL_DSLLV:
case R4300i_SPECIAL_DSRLV:
case R4300i_SPECIAL_DSRAV:
case R4300i_SPECIAL_ADD:
case R4300i_SPECIAL_ADDU:
case R4300i_SPECIAL_SUB:
case R4300i_SPECIAL_SUBU:
case R4300i_SPECIAL_AND:
case R4300i_SPECIAL_OR:
case R4300i_SPECIAL_XOR:
case R4300i_SPECIAL_NOR:
case R4300i_SPECIAL_SLT:
case R4300i_SPECIAL_SLTU:
case R4300i_SPECIAL_DADD:
case R4300i_SPECIAL_DADDU:
case R4300i_SPECIAL_DSUB:
case R4300i_SPECIAL_DSUBU:
case R4300i_SPECIAL_DSLL:
case R4300i_SPECIAL_DSRL:
case R4300i_SPECIAL_DSRA:
case R4300i_SPECIAL_DSLL32:
case R4300i_SPECIAL_DSRL32:
case R4300i_SPECIAL_DSRA32:
if (Command.rd == 0)
{
return false;
}
if (Command.rd == Reg1 || Command.rd == Reg2)
{
return true;
}
break;
case R4300i_SPECIAL_MULT:
case R4300i_SPECIAL_MULTU:
case R4300i_SPECIAL_DIV:
case R4300i_SPECIAL_DIVU:
case R4300i_SPECIAL_DMULT:
case R4300i_SPECIAL_DMULTU:
case R4300i_SPECIAL_DDIV:
case R4300i_SPECIAL_DDIVU:
break;
default:
if (CDebugSettings::HaveDebugger())
{
g_Notify->DisplayError(stdstr_f("Does %s effect delay slot at %X?", R4300iInstruction(PC + 4, Command.Value).Name(), PC).c_str());
}
return true;
}
break;
case R4300i_CP0:
switch (Command.rs)
{
case R4300i_COP0_MT: break;
case R4300i_COP0_MF:
if (Command.rt == 0)
{
return false;
}
if (Command.rt == Reg1 || Command.rt == Reg2)
{
return true;
}
break;
default:
if ((Command.rs & 0x10) != 0)
{
switch (Command.funct)
{
case R4300i_COP0_CO_TLBR: break;
case R4300i_COP0_CO_TLBWI: break;
case R4300i_COP0_CO_TLBWR: break;
case R4300i_COP0_CO_TLBP: break;
default:
if (CDebugSettings::HaveDebugger())
{
g_Notify->DisplayError(stdstr_f("Does %s effect delay slot at %X?\n6", R4300iInstruction(PC + 4, Command.Value).Name(), PC).c_str());
}
return true;
}
}
else
{
if (CDebugSettings::HaveDebugger())
{
g_Notify->DisplayError(stdstr_f("Does %s effect delay slot at %X?\n7", R4300iInstruction(PC + 4, Command.Value).Name(), PC).c_str());
}
return true;
}
}
break;
case R4300i_CP1:
switch (Command.fmt)
{
case R4300i_COP1_MF:
if (Command.rt == 0)
{
return false;
}
if (Command.rt == Reg1 || Command.rt == Reg2)
{
return true;
}
break;
case R4300i_COP1_CF: break;
case R4300i_COP1_MT: break;
case R4300i_COP1_CT: break;
case R4300i_COP1_S: break;
case R4300i_COP1_D: break;
case R4300i_COP1_W: break;
case R4300i_COP1_L: break;
default:
if (CDebugSettings::HaveDebugger())
{
g_Notify->DisplayError(stdstr_f("Does %s effect delay slot at %X?", R4300iInstruction(PC + 4, Command.Value).Name(), PC).c_str());
}
return true;
}
break;
case R4300i_ANDI:
case R4300i_ORI:
case R4300i_XORI:
case R4300i_LUI:
case R4300i_ADDI:
case R4300i_ADDIU:
case R4300i_SLTI:
case R4300i_SLTIU:
case R4300i_DADDI:
case R4300i_DADDIU:
case R4300i_LB:
case R4300i_LH:
case R4300i_LW:
case R4300i_LWL:
case R4300i_LWR:
case R4300i_LDL:
case R4300i_LDR:
case R4300i_LBU:
case R4300i_LHU:
case R4300i_LD:
case R4300i_LWC1:
case R4300i_LDC1:
if (Command.rt == 0)
{
return false;
}
if (Command.rt == Reg1 || Command.rt == Reg2)
{
return true;
}
break;
case R4300i_CACHE: break;
case R4300i_SB: break;
case R4300i_SH: break;
case R4300i_SW: break;
case R4300i_SWR: break;
case R4300i_SWL: break;
case R4300i_SWC1: break;
case R4300i_SDC1: break;
case R4300i_SD: break;
default:
if (CDebugSettings::HaveDebugger())
{
g_Notify->DisplayError(stdstr_f("Does %s effect delay slot at %X?", R4300iInstruction(PC + 4, Command.Value).Name(), PC).c_str());
}
return true;
}
return false;
}
void CInterpreterCPU::BuildCPU() void CInterpreterCPU::BuildCPU()
{ {
R4300iOp::m_TestTimer = false; R4300iOp::m_TestTimer = false;

View File

@ -700,8 +700,6 @@ R4300iOp::Func * R4300iOp::BuildInterpreter()
return Jump_Opcode; return Jump_Opcode;
} }
bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2);
// Opcode functions // Opcode functions
void R4300iOp::J() void R4300iOp::J()
@ -734,7 +732,8 @@ void R4300iOp::BEQ()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, m_Opcode.rt)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -754,7 +753,8 @@ void R4300iOp::BNE()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, m_Opcode.rt)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -774,7 +774,8 @@ void R4300iOp::BLEZ()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -794,7 +795,8 @@ void R4300iOp::BGTZ()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -895,7 +897,8 @@ void R4300iOp::BEQL()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, m_Opcode.rt)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -916,7 +919,8 @@ void R4300iOp::BNEL()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, m_Opcode.rt)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -937,7 +941,8 @@ void R4300iOp::BLEZL()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -958,7 +963,8 @@ void R4300iOp::BGTZL()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -1660,9 +1666,10 @@ void R4300iOp::REGIMM_BLTZ()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare((*_PROGRAM_COUNTER), m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
CInterpreterCPU::InPermLoop(); g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
} }
} }
@ -1680,9 +1687,10 @@ void R4300iOp::REGIMM_BGEZ()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare((*_PROGRAM_COUNTER), m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
CInterpreterCPU::InPermLoop(); g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
} }
} }
@ -1700,9 +1708,10 @@ void R4300iOp::REGIMM_BLTZL()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare((*_PROGRAM_COUNTER), m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
CInterpreterCPU::InPermLoop(); g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
} }
} }
@ -1721,9 +1730,10 @@ void R4300iOp::REGIMM_BGEZL()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare((*_PROGRAM_COUNTER), m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
CInterpreterCPU::InPermLoop(); g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
} }
} }
@ -1742,9 +1752,10 @@ void R4300iOp::REGIMM_BLTZAL()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare((*_PROGRAM_COUNTER), m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
CInterpreterCPU::InPermLoop(); g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
} }
} }
@ -1775,9 +1786,10 @@ void R4300iOp::REGIMM_BGEZAL()
return; return;
} }
} }
if (!DelaySlotEffectsCompare((*_PROGRAM_COUNTER), m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
CInterpreterCPU::InPermLoop(); g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
} }
} }

View File

@ -4,12 +4,11 @@
#include <Project64-core/N64System/N64System.h> #include <Project64-core/N64System/N64System.h>
#include <Project64-core/N64System/Mips/MemoryVirtualMem.h> #include <Project64-core/N64System/Mips/MemoryVirtualMem.h>
#include <Project64-core/N64System/Mips/SystemTiming.h> #include <Project64-core/N64System/Mips/SystemTiming.h>
#include <Project64-core/N64System/Mips/R4300iInstruction.h>
#include <Project64-core/N64System/Interpreter/InterpreterCPU.h> #include <Project64-core/N64System/Interpreter/InterpreterCPU.h>
#include <Project64-core/Logging.h> #include <Project64-core/Logging.h>
#include <Project64-core/Debugger.h> #include <Project64-core/Debugger.h>
bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2);
#define TEST_COP1_USABLE_EXCEPTION \ #define TEST_COP1_USABLE_EXCEPTION \
if ((g_Reg->STATUS_REGISTER & STATUS_CU1) == 0) {\ if ((g_Reg->STATUS_REGISTER & STATUS_CU1) == 0) {\
g_Reg->DoCopUnusableException(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP,1);\ g_Reg->DoCopUnusableException(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP,1);\
@ -632,7 +631,8 @@ void R4300iOp32::BEQ()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, m_Opcode.rt)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -652,7 +652,8 @@ void R4300iOp32::BNE()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, m_Opcode.rt)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -672,7 +673,8 @@ void R4300iOp32::BLEZ()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -692,7 +694,8 @@ void R4300iOp32::BGTZ()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -793,7 +796,8 @@ void R4300iOp32::BEQL()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, m_Opcode.rt)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -814,7 +818,8 @@ void R4300iOp32::BNEL()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, m_Opcode.rt)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -835,7 +840,8 @@ void R4300iOp32::BLEZL()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -856,7 +862,8 @@ void R4300iOp32::BGTZL()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare(*_PROGRAM_COUNTER, m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
@ -1075,9 +1082,10 @@ void R4300iOp32::REGIMM_BLTZ()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare((*_PROGRAM_COUNTER), m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
CInterpreterCPU::InPermLoop(); g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
} }
} }
@ -1095,9 +1103,10 @@ void R4300iOp32::REGIMM_BGEZ()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare((*_PROGRAM_COUNTER), m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
CInterpreterCPU::InPermLoop(); g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
} }
} }
@ -1115,9 +1124,10 @@ void R4300iOp32::REGIMM_BLTZL()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare((*_PROGRAM_COUNTER), m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
CInterpreterCPU::InPermLoop(); g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
} }
} }
@ -1136,9 +1146,10 @@ void R4300iOp32::REGIMM_BGEZL()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare((*_PROGRAM_COUNTER), m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
CInterpreterCPU::InPermLoop(); g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
} }
} }
@ -1157,9 +1168,10 @@ void R4300iOp32::REGIMM_BLTZAL()
g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation)
{ {
if (!DelaySlotEffectsCompare((*_PROGRAM_COUNTER), m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
CInterpreterCPU::InPermLoop(); g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
} }
} }
@ -1190,9 +1202,10 @@ void R4300iOp32::REGIMM_BGEZAL()
return; return;
} }
} }
if (!DelaySlotEffectsCompare((*_PROGRAM_COUNTER), m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
CInterpreterCPU::InPermLoop(); g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY;
} }
} }
} }

View File

@ -77,6 +77,253 @@ bool R4300iInstruction::HasDelaySlot(void) const
return false; return false;
} }
bool R4300iInstruction::DelaySlotEffectsCompare(uint32_t DelayInstruction) const
{
R4300iInstruction DelaySlot(m_Address + 4, DelayInstruction);
uint32_t Reg1 = 0, Reg2 = 0;
switch (m_Instruction.op)
{
case R4300i_SPECIAL:
switch (m_Instruction.funct)
{
case R4300i_SPECIAL_JR:
case R4300i_SPECIAL_JALR:
Reg1 = m_Instruction.rs;
break;
default:
return false;
}
break;
case R4300i_REGIMM:
switch (m_Instruction.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:
Reg1 = m_Instruction.rs;
break;
default:
return false;
}
break;
case R4300i_BEQ:
case R4300i_BNE:
case R4300i_BEQL:
case R4300i_BNEL:
Reg1 = m_Instruction.rs;
Reg2 = m_Instruction.rt;
break;
case R4300i_BLEZ:
case R4300i_BGTZ:
case R4300i_BLEZL:
case R4300i_BGTZL:
Reg1 = m_Instruction.rs;
break;
case R4300i_CP1:
if (m_Instruction.fmt == R4300i_COP1_BC)
{
if (DelaySlot.m_Instruction.op == R4300i_CP1)
{
if ((DelaySlot.m_Instruction.fmt == R4300i_COP1_S && (DelaySlot.m_Instruction.funct & 0x30) == 0x30) ||
(DelaySlot.m_Instruction.fmt == R4300i_COP1_D && (DelaySlot.m_Instruction.funct & 0x30) == 0x30))
{
return true;
}
}
}
return false;
break;
default:
return false;
}
switch (DelaySlot.m_Instruction.op)
{
case R4300i_SPECIAL:
switch (DelaySlot.m_Instruction.funct)
{
case R4300i_SPECIAL_SLL:
case R4300i_SPECIAL_SRL:
case R4300i_SPECIAL_SRA:
case R4300i_SPECIAL_SLLV:
case R4300i_SPECIAL_SRLV:
case R4300i_SPECIAL_SRAV:
case R4300i_SPECIAL_MFHI:
case R4300i_SPECIAL_MTHI:
case R4300i_SPECIAL_MFLO:
case R4300i_SPECIAL_MTLO:
case R4300i_SPECIAL_DSLLV:
case R4300i_SPECIAL_DSRLV:
case R4300i_SPECIAL_DSRAV:
case R4300i_SPECIAL_ADD:
case R4300i_SPECIAL_ADDU:
case R4300i_SPECIAL_SUB:
case R4300i_SPECIAL_SUBU:
case R4300i_SPECIAL_AND:
case R4300i_SPECIAL_OR:
case R4300i_SPECIAL_XOR:
case R4300i_SPECIAL_NOR:
case R4300i_SPECIAL_SLT:
case R4300i_SPECIAL_SLTU:
case R4300i_SPECIAL_DADD:
case R4300i_SPECIAL_DADDU:
case R4300i_SPECIAL_DSUB:
case R4300i_SPECIAL_DSUBU:
case R4300i_SPECIAL_DSLL:
case R4300i_SPECIAL_DSRL:
case R4300i_SPECIAL_DSRA:
case R4300i_SPECIAL_DSLL32:
case R4300i_SPECIAL_DSRL32:
case R4300i_SPECIAL_DSRA32:
if (DelaySlot.m_Instruction.rd == 0)
{
return false;
}
if (DelaySlot.m_Instruction.rd == Reg1 || DelaySlot.m_Instruction.rd == Reg2)
{
return true;
}
break;
case R4300i_SPECIAL_MULT:
case R4300i_SPECIAL_MULTU:
case R4300i_SPECIAL_DIV:
case R4300i_SPECIAL_DIVU:
case R4300i_SPECIAL_DMULT:
case R4300i_SPECIAL_DMULTU:
case R4300i_SPECIAL_DDIV:
case R4300i_SPECIAL_DDIVU:
break;
default:
if (CDebugSettings::HaveDebugger())
{
g_Notify->DisplayError(stdstr_f("Does %s effect delay slot at %X?", DelaySlot.Name(), m_Address).c_str());
}
return true;
}
break;
case R4300i_CP0:
switch (DelaySlot.m_Instruction.rs)
{
case R4300i_COP0_MT: break;
case R4300i_COP0_MF:
if (DelaySlot.m_Instruction.rt == 0)
{
return false;
}
if (DelaySlot.m_Instruction.rt == Reg1 || DelaySlot.m_Instruction.rt == Reg2)
{
return true;
}
break;
default:
if ((DelaySlot.m_Instruction.rs & 0x10) != 0)
{
switch (DelaySlot.m_Instruction.funct)
{
case R4300i_COP0_CO_TLBR: break;
case R4300i_COP0_CO_TLBWI: break;
case R4300i_COP0_CO_TLBWR: break;
case R4300i_COP0_CO_TLBP: break;
default:
if (CDebugSettings::HaveDebugger())
{
g_Notify->DisplayError(stdstr_f("Does %s effect delay slot at %X?\n6", DelaySlot.Name(), m_Address).c_str());
}
return true;
}
}
else
{
if (CDebugSettings::HaveDebugger())
{
g_Notify->DisplayError(stdstr_f("Does %s effect delay slot at %X?\n7", DelaySlot.Name(), m_Address).c_str());
}
return true;
}
}
break;
case R4300i_CP1:
switch (DelaySlot.m_Instruction.fmt)
{
case R4300i_COP1_MF:
if (DelaySlot.m_Instruction.rt == 0)
{
return false;
}
if (DelaySlot.m_Instruction.rt == Reg1 || DelaySlot.m_Instruction.rt == Reg2)
{
return true;
}
break;
case R4300i_COP1_CF: break;
case R4300i_COP1_MT: break;
case R4300i_COP1_CT: break;
case R4300i_COP1_S: break;
case R4300i_COP1_D: break;
case R4300i_COP1_W: break;
case R4300i_COP1_L: break;
default:
if (CDebugSettings::HaveDebugger())
{
g_Notify->DisplayError(stdstr_f("Does %s effect delay slot at %X?", DelaySlot.Name(), m_Address).c_str());
}
return true;
}
break;
case R4300i_ANDI:
case R4300i_ORI:
case R4300i_XORI:
case R4300i_LUI:
case R4300i_ADDI:
case R4300i_ADDIU:
case R4300i_SLTI:
case R4300i_SLTIU:
case R4300i_DADDI:
case R4300i_DADDIU:
case R4300i_LB:
case R4300i_LH:
case R4300i_LW:
case R4300i_LWL:
case R4300i_LWR:
case R4300i_LDL:
case R4300i_LDR:
case R4300i_LBU:
case R4300i_LHU:
case R4300i_LD:
case R4300i_LWC1:
case R4300i_LDC1:
if (DelaySlot.m_Instruction.rt == 0)
{
return false;
}
if (DelaySlot.m_Instruction.rt == Reg1 || DelaySlot.m_Instruction.rt == Reg2)
{
return true;
}
break;
case R4300i_CACHE: break;
case R4300i_SB: break;
case R4300i_SH: break;
case R4300i_SW: break;
case R4300i_SWR: break;
case R4300i_SWL: break;
case R4300i_SWC1: break;
case R4300i_SDC1: break;
case R4300i_SD: break;
default:
if (CDebugSettings::HaveDebugger())
{
g_Notify->DisplayError(stdstr_f("Does %s effect delay slot at %X?", DelaySlot.Name(), m_Address).c_str());
}
return true;
}
return false;
}
const char * R4300iInstruction::FPR_Type(uint32_t COP1OpCode) const char * R4300iInstruction::FPR_Type(uint32_t COP1OpCode)
{ {
if (COP1OpCode == R4300i_COP1_S) { return "S"; }; if (COP1OpCode == R4300i_COP1_S) { return "S"; };

View File

@ -12,6 +12,7 @@ public:
std::string NameAndParam(); std::string NameAndParam();
bool HasDelaySlot(void) const; bool HasDelaySlot(void) const;
bool DelaySlotEffectsCompare(uint32_t DelayInstruction) const;
private: private:
R4300iInstruction(void); R4300iInstruction(void);

View File

@ -8,8 +8,6 @@
#include <Project64-core/N64System/N64System.h> #include <Project64-core/N64System/N64System.h>
#include <Project64-core/N64System/Mips/R4300iInstruction.h> #include <Project64-core/N64System/Mips/R4300iInstruction.h>
bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2);
#if defined(ANDROID) && (defined(__arm__) || defined(_M_ARM)) #if defined(ANDROID) && (defined(__arm__) || defined(_M_ARM))
/* bug-fix to implement __clear_cache (missing in Android; http://code.google.com/p/android/issues/detail?id=1803) */ /* bug-fix to implement __clear_cache (missing in Android; http://code.google.com/p/android/issues/detail?id=1803) */
extern "C" void __clear_cache_android(uint8_t* begin, uint8_t *end); extern "C" void __clear_cache_android(uint8_t* begin, uint8_t *end);
@ -493,7 +491,13 @@ bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t &
} }
else else
{ {
if (TargetPC == PC && !DelaySlotEffectsCompare(PC, Command.rs, 0)) R4300iOpcode DelaySlot;
if (!g_MMU->MemoryValue32(PC + 4, DelaySlot.Value))
{
g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD));
}
if (TargetPC == PC && !R4300iInstruction(PC, Command.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
PermLoop = true; PermLoop = true;
} }
@ -519,7 +523,12 @@ bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t &
} }
else else
{ {
if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt)) R4300iOpcode DelaySlot;
if (!g_MMU->MemoryValue32(PC + 4, DelaySlot.Value))
{
g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD));
}
if (!R4300iInstruction(PC, Command.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
PermLoop = true; PermLoop = true;
} }
@ -537,7 +546,12 @@ bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t &
TargetPC = PC + ((int16_t)Command.offset << 2) + 4; TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
if (TargetPC == PC) if (TargetPC == PC)
{ {
if (!DelaySlotEffectsCompare(PC, Command.rs, 0)) R4300iOpcode DelaySlot;
if (!g_MMU->MemoryValue32(PC + 4, DelaySlot.Value))
{
g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD));
}
if (!R4300iInstruction(PC, Command.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
PermLoop = true; PermLoop = true;
} }
@ -583,8 +597,12 @@ bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t &
{ {
ContinuePC = PC + 8; ContinuePC = PC + 8;
} }
R4300iOpcode DelaySlot;
if (TargetPC == PC && !DelaySlotEffectsCompare(PC, Command.rs, Command.rt)) if (!g_MMU->MemoryValue32(PC + 4, DelaySlot.Value))
{
g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD));
}
if (TargetPC == PC && !R4300iInstruction(PC, Command.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
PermLoop = true; PermLoop = true;
} }
@ -603,7 +621,12 @@ bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t &
{ {
if (TargetPC == PC) if (TargetPC == PC)
{ {
if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt)) R4300iOpcode DelaySlot;
if (!g_MMU->MemoryValue32(PC + 4, DelaySlot.Value))
{
g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD));
}
if (!R4300iInstruction(PC, Command.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
PermLoop = true; PermLoop = true;
} }
@ -701,7 +724,12 @@ bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t &
TargetPC = PC + ((int16_t)Command.offset << 2) + 4; TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
if (TargetPC == PC) if (TargetPC == PC)
{ {
if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt)) R4300iOpcode DelaySlot;
if (!g_MMU->MemoryValue32(PC + 4, DelaySlot.Value))
{
g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD));
}
if (!R4300iInstruction(PC, Command.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
PermLoop = true; PermLoop = true;
} }
@ -720,7 +748,12 @@ bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t &
ContinuePC = PC + 8; ContinuePC = PC + 8;
if (TargetPC == PC) if (TargetPC == PC)
{ {
if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt)) R4300iOpcode DelaySlot;
if (!g_MMU->MemoryValue32(PC + 4, DelaySlot.Value))
{
g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD));
}
if (!R4300iInstruction(PC, Command.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
PermLoop = true; PermLoop = true;
} }

View File

@ -13,94 +13,6 @@
#include <Project64-core/ExceptionHandler.h> #include <Project64-core/ExceptionHandler.h>
#include <Project64-core/Debugger.h> #include <Project64-core/Debugger.h>
void InPermLoop();
bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2);
static bool DelaySlotEffectsJump(uint32_t JumpPC)
{
R4300iOpcode Command;
if (!g_MMU->MemoryValue32(JumpPC, Command.Value))
{
return true;
}
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:
{
bool EffectDelaySlot = false;
R4300iOpcode NewCommand;
if (!g_MMU->MemoryValue32(JumpPC + 4, NewCommand.Value))
{
return true;
}
if (NewCommand.op == R4300i_CP1)
{
if (NewCommand.fmt == R4300i_COP1_S && (NewCommand.funct & 0x30) == 0x30)
{
EffectDelaySlot = true;
}
if (NewCommand.fmt == R4300i_COP1_D && (NewCommand.funct & 0x30) == 0x30)
{
EffectDelaySlot = true;
}
}
return EffectDelaySlot;
}
break;
}
break;
}
break;
case R4300i_BEQL:
case R4300i_BNEL:
case R4300i_BLEZL:
case R4300i_BGTZL:
return DelaySlotEffectsCompare(JumpPC, Command.rs, Command.rt);
}
return true;
}
CCodeSection::CCodeSection(CCodeBlock * CodeBlock, uint32_t EnterPC, uint32_t ID, bool LinkAllowed) : CCodeSection::CCodeSection(CCodeBlock * CodeBlock, uint32_t EnterPC, uint32_t ID, bool LinkAllowed) :
m_BlockInfo(CodeBlock), m_BlockInfo(CodeBlock),
m_SectionID(ID), m_SectionID(ID),
@ -148,7 +60,10 @@ void CCodeSection::GenerateSectionLinkage()
// Handle permanent loop // Handle permanent loop
if (m_RecompilerOps->GetCurrentPC() == m_Jump.TargetPC && (m_Cont.FallThrough == false)) if (m_RecompilerOps->GetCurrentPC() == m_Jump.TargetPC && (m_Cont.FallThrough == false))
{ {
if (!DelaySlotEffectsJump(m_RecompilerOps->GetCurrentPC())) R4300iOpcode JumpOp, DelaySlot;
if (g_MMU->MemoryValue32(m_RecompilerOps->GetCurrentPC(), JumpOp.Value) &&
g_MMU->MemoryValue32(m_RecompilerOps->GetCurrentPC() + 4, DelaySlot.Value) &&
!R4300iInstruction(m_RecompilerOps->GetCurrentPC(), JumpOp.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
m_RecompilerOps->CompileInPermLoop(m_Jump.RegSet, m_RecompilerOps->GetCurrentPC()); m_RecompilerOps->CompileInPermLoop(m_Jump.RegSet, m_RecompilerOps->GetCurrentPC());
} }
@ -480,12 +395,12 @@ bool CCodeSection::GenerateNativeCode(uint32_t Test)
case R4300i_REGIMM: case R4300i_REGIMM:
switch (Opcode.rt) switch (Opcode.rt)
{ {
case R4300i_REGIMM_BLTZ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBLTZ, CRecompilerOps::BranchTypeRs, false); break; case R4300i_REGIMM_BLTZ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBLTZ, false); break;
case R4300i_REGIMM_BGEZ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBGEZ, CRecompilerOps::BranchTypeRs, false); break; case R4300i_REGIMM_BGEZ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBGEZ, false); break;
case R4300i_REGIMM_BLTZL: m_RecompilerOps->Compile_BranchLikely(CRecompilerOps::CompareTypeBLTZ, false); break; case R4300i_REGIMM_BLTZL: m_RecompilerOps->Compile_BranchLikely(CRecompilerOps::CompareTypeBLTZ, false); break;
case R4300i_REGIMM_BGEZL: m_RecompilerOps->Compile_BranchLikely(CRecompilerOps::CompareTypeBGEZ, false); break; case R4300i_REGIMM_BGEZL: m_RecompilerOps->Compile_BranchLikely(CRecompilerOps::CompareTypeBGEZ, false); break;
case R4300i_REGIMM_BLTZAL: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBLTZ, CRecompilerOps::BranchTypeRs, true); break; case R4300i_REGIMM_BLTZAL: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBLTZ, true); break;
case R4300i_REGIMM_BGEZAL: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBGEZ, CRecompilerOps::BranchTypeRs, true); break; case R4300i_REGIMM_BGEZAL: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBGEZ, true); break;
case R4300i_REGIMM_TEQI: m_RecompilerOps->Compile_TrapCompare(CRecompilerOps::TRAP_COMPARE::CompareTypeTEQI); break; case R4300i_REGIMM_TEQI: m_RecompilerOps->Compile_TrapCompare(CRecompilerOps::TRAP_COMPARE::CompareTypeTEQI); break;
case R4300i_REGIMM_TNEI: m_RecompilerOps->Compile_TrapCompare(CRecompilerOps::TRAP_COMPARE::CompareTypeTNEI); break; case R4300i_REGIMM_TNEI: m_RecompilerOps->Compile_TrapCompare(CRecompilerOps::TRAP_COMPARE::CompareTypeTNEI); break;
case R4300i_REGIMM_TGEI: m_RecompilerOps->Compile_TrapCompare(CRecompilerOps::TRAP_COMPARE::CompareTypeTGEI); break; case R4300i_REGIMM_TGEI: m_RecompilerOps->Compile_TrapCompare(CRecompilerOps::TRAP_COMPARE::CompareTypeTGEI); break;
@ -496,10 +411,10 @@ bool CCodeSection::GenerateNativeCode(uint32_t Test)
m_RecompilerOps->UnknownOpcode(); break; m_RecompilerOps->UnknownOpcode(); break;
} }
break; break;
case R4300i_BEQ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBEQ, CRecompilerOps::BranchTypeRsRt, false); break; case R4300i_BEQ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBEQ, false); break;
case R4300i_BNE: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBNE, CRecompilerOps::BranchTypeRsRt, false); break; case R4300i_BNE: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBNE, false); break;
case R4300i_BGTZ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBGTZ, CRecompilerOps::BranchTypeRs, false); break; case R4300i_BGTZ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBGTZ, false); break;
case R4300i_BLEZ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBLEZ, CRecompilerOps::BranchTypeRs, false); break; case R4300i_BLEZ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBLEZ, false); break;
case R4300i_J: m_RecompilerOps->J(); break; case R4300i_J: m_RecompilerOps->J(); break;
case R4300i_JAL: m_RecompilerOps->JAL(); break; case R4300i_JAL: m_RecompilerOps->JAL(); break;
case R4300i_ADDI: m_RecompilerOps->ADDI(); break; case R4300i_ADDI: m_RecompilerOps->ADDI(); break;
@ -546,8 +461,8 @@ bool CCodeSection::GenerateNativeCode(uint32_t Test)
case R4300i_COP1_BC: case R4300i_COP1_BC:
switch (Opcode.ft) switch (Opcode.ft)
{ {
case R4300i_COP1_BC_BCF: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeCOP1BCF, CRecompilerOps::BranchTypeCop1, false); break; case R4300i_COP1_BC_BCF: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeCOP1BCF, false); break;
case R4300i_COP1_BC_BCT: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeCOP1BCT, CRecompilerOps::BranchTypeCop1, false); break; case R4300i_COP1_BC_BCT: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeCOP1BCT, false); break;
case R4300i_COP1_BC_BCFL: m_RecompilerOps->Compile_BranchLikely(CRecompilerOps::CompareTypeCOP1BCF, false); break; case R4300i_COP1_BC_BCFL: m_RecompilerOps->Compile_BranchLikely(CRecompilerOps::CompareTypeCOP1BCF, false); break;
case R4300i_COP1_BC_BCTL: m_RecompilerOps->Compile_BranchLikely(CRecompilerOps::CompareTypeCOP1BCT, false); break; case R4300i_COP1_BC_BCTL: m_RecompilerOps->Compile_BranchLikely(CRecompilerOps::CompareTypeCOP1BCT, false); break;
default: default:

View File

@ -13,8 +13,6 @@
#define CHECKED_BUILD 1 #define CHECKED_BUILD 1
#endif #endif
bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2);
LoopAnalysis::LoopAnalysis(CCodeBlock * CodeBlock, CCodeSection * Section) : LoopAnalysis::LoopAnalysis(CCodeBlock * CodeBlock, CCodeSection * Section) :
m_EnterSection(Section), m_EnterSection(Section),
m_BlockInfo(CodeBlock), m_BlockInfo(CodeBlock),
@ -261,7 +259,10 @@ bool LoopAnalysis::CheckLoopRegisterUsage(CCodeSection * Section)
} }
if (m_PC == Section->m_Jump.TargetPC) if (m_PC == Section->m_Jump.TargetPC)
{ {
if (!DelaySlotEffectsCompare(m_PC, m_Command.rs, 0) && !Section->m_Jump.PermLoop) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(m_PC + 4, DelaySlot.Value) &&
!R4300iInstruction(m_PC, m_Command.Value).DelaySlotEffectsCompare(DelaySlot.Value) &&
!Section->m_Jump.PermLoop)
{ {
g_Notify->BreakPoint(__FILE__, __LINE__); g_Notify->BreakPoint(__FILE__, __LINE__);
} }
@ -291,7 +292,10 @@ bool LoopAnalysis::CheckLoopRegisterUsage(CCodeSection * Section)
}*/ }*/
if (m_PC == m_PC + ((int16_t)m_Command.offset << 2) + 4) if (m_PC == m_PC + ((int16_t)m_Command.offset << 2) + 4)
{ {
if (!DelaySlotEffectsCompare(m_PC, m_Command.rs, 0) && !Section->m_Jump.PermLoop) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(m_PC + 4, DelaySlot.Value) &&
!R4300iInstruction(m_PC, m_Command.Value).DelaySlotEffectsCompare(DelaySlot.Value) &&
!Section->m_Jump.PermLoop)
{ {
g_Notify->BreakPoint(__FILE__, __LINE__); g_Notify->BreakPoint(__FILE__, __LINE__);
} }
@ -351,7 +355,10 @@ bool LoopAnalysis::CheckLoopRegisterUsage(CCodeSection * Section)
} }
if (m_PC == Section->m_Jump.TargetPC) if (m_PC == Section->m_Jump.TargetPC)
{ {
if (!DelaySlotEffectsCompare(m_PC, m_Command.rs, m_Command.rt) && !Section->m_Jump.PermLoop) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(m_PC + 4, DelaySlot.Value) &&
!R4300iInstruction(m_PC, m_Command.Value).DelaySlotEffectsCompare(DelaySlot.Value) &&
!Section->m_Jump.PermLoop)
{ {
g_Notify->BreakPoint(__FILE__, __LINE__); g_Notify->BreakPoint(__FILE__, __LINE__);
} }
@ -380,7 +387,10 @@ bool LoopAnalysis::CheckLoopRegisterUsage(CCodeSection * Section)
} }
if (m_PC == Section->m_Jump.TargetPC) if (m_PC == Section->m_Jump.TargetPC)
{ {
if (!DelaySlotEffectsCompare(m_PC, m_Command.rs, m_Command.rt) && !Section->m_Jump.PermLoop) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(m_PC + 4, DelaySlot.Value) &&
!R4300iInstruction(m_PC, m_Command.Value).DelaySlotEffectsCompare(DelaySlot.Value) &&
!Section->m_Jump.PermLoop)
{ {
g_Notify->BreakPoint(__FILE__, __LINE__); g_Notify->BreakPoint(__FILE__, __LINE__);
} }
@ -562,7 +572,10 @@ bool LoopAnalysis::CheckLoopRegisterUsage(CCodeSection * Section)
}*/ }*/
if (m_PC == m_PC + ((int16_t)m_Command.offset << 2) + 4) if (m_PC == m_PC + ((int16_t)m_Command.offset << 2) + 4)
{ {
if (!DelaySlotEffectsCompare(m_PC, m_Command.rs, m_Command.rt) && !Section->m_Jump.PermLoop) R4300iOpcode DelaySlot;
if (g_MMU->MemoryValue32(m_PC + 4, DelaySlot.Value) &&
!R4300iInstruction(m_PC, m_Command.Value).DelaySlotEffectsCompare(DelaySlot.Value) &&
!Section->m_Jump.PermLoop)
{ {
g_Notify->BreakPoint(__FILE__, __LINE__); g_Notify->BreakPoint(__FILE__, __LINE__);
} }

View File

@ -45,7 +45,7 @@ public:
virtual void Compile_TrapCompare(TRAP_COMPARE CompareType) = 0; virtual void Compile_TrapCompare(TRAP_COMPARE CompareType) = 0;
// Branch functions // Branch functions
virtual void Compile_Branch(BRANCH_COMPARE CompareType, BRANCH_TYPE BranchType, bool Link) = 0; virtual void Compile_Branch(BRANCH_COMPARE CompareType, bool Link) = 0;
virtual void Compile_BranchLikely(BRANCH_COMPARE CompareType, bool Link) = 0; virtual void Compile_BranchLikely(BRANCH_COMPARE CompareType, bool Link) = 0;
// Opcode functions // Opcode functions

View File

@ -364,8 +364,6 @@ void CX86RecompilerOps::CompileWriteTLBMiss(x86Reg AddressReg, x86Reg LookUpReg)
CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::TLBWriteMiss, false, JeLabel32); CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::TLBWriteMiss, false, JeLabel32);
} }
bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2);
// Trap functions // Trap functions
void CX86RecompilerOps::Compile_TrapCompare(TRAP_COMPARE CompareType) void CX86RecompilerOps::Compile_TrapCompare(TRAP_COMPARE CompareType)
{ {
@ -462,7 +460,7 @@ void CX86RecompilerOps::Compile_BranchCompare(BRANCH_COMPARE CompareType)
} }
} }
void CX86RecompilerOps::Compile_Branch(BRANCH_COMPARE CompareType, BRANCH_TYPE BranchType, bool Link) void CX86RecompilerOps::Compile_Branch(BRANCH_COMPARE CompareType, bool Link)
{ {
static CRegInfo RegBeforeDelay; static CRegInfo RegBeforeDelay;
static bool EffectDelaySlot; static bool EffectDelaySlot;
@ -480,33 +478,12 @@ void CX86RecompilerOps::Compile_Branch(BRANCH_COMPARE CompareType, BRANCH_TYPE B
if ((m_CompilePC & 0xFFC) != 0xFFC) if ((m_CompilePC & 0xFFC) != 0xFFC)
{ {
switch (BranchType) R4300iOpcode DelaySlot;
if (!g_MMU->MemoryValue32(m_CompilePC + 4, DelaySlot.Value))
{ {
case BranchTypeRs: EffectDelaySlot = DelaySlotEffectsCompare(m_CompilePC, m_Opcode.rs, 0); break; g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD));
case BranchTypeRsRt: EffectDelaySlot = DelaySlotEffectsCompare(m_CompilePC, m_Opcode.rs, m_Opcode.rt); break;
case BranchTypeCop1:
{
R4300iOpcode Command;
if (!g_MMU->MemoryValue32(m_CompilePC + 4, Command.Value))
{
g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD));
}
EffectDelaySlot = false;
if (Command.op == R4300i_CP1)
{
if ((Command.fmt == R4300i_COP1_S && (Command.funct & 0x30) == 0x30) ||
(Command.fmt == R4300i_COP1_D && (Command.funct & 0x30) == 0x30))
{
EffectDelaySlot = true;
}
}
}
break;
default:
if (HaveDebugger()) { g_Notify->DisplayError("Unknown branch type"); }
} }
EffectDelaySlot = R4300iInstruction(m_CompilePC, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value);
} }
else else
{ {
@ -4323,7 +4300,13 @@ void CX86RecompilerOps::SPECIAL_JR()
m_Section->m_Cont.LinkLocation = nullptr; m_Section->m_Cont.LinkLocation = nullptr;
m_Section->m_Cont.LinkLocation2 = nullptr; m_Section->m_Cont.LinkLocation2 = nullptr;
if (DelaySlotEffectsCompare(m_CompilePC, m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (!g_MMU->MemoryValue32(m_CompilePC + 4, DelaySlot.Value))
{
g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD));
}
if (R4300iInstruction(m_CompilePC, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
if (IsConst(m_Opcode.rs)) if (IsConst(m_Opcode.rs))
{ {
@ -4342,7 +4325,13 @@ void CX86RecompilerOps::SPECIAL_JR()
} }
else if (m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT_DONE) else if (m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT_DONE)
{ {
if (DelaySlotEffectsCompare(m_CompilePC, m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (!g_MMU->MemoryValue32(m_CompilePC + 4, DelaySlot.Value))
{
g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD));
}
if (R4300iInstruction(m_CompilePC, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
CompileExit(m_CompilePC, (uint32_t)-1, m_RegWorkingSet, CExitInfo::Normal, true, nullptr); CompileExit(m_CompilePC, (uint32_t)-1, m_RegWorkingSet, CExitInfo::Normal, true, nullptr);
} }
@ -4379,7 +4368,13 @@ void CX86RecompilerOps::SPECIAL_JALR()
{ {
if (m_PipelineStage == PIPELINE_STAGE_NORMAL) if (m_PipelineStage == PIPELINE_STAGE_NORMAL)
{ {
if (DelaySlotEffectsCompare(m_CompilePC, m_Opcode.rs, 0) && (m_CompilePC & 0xFFC) != 0xFFC) R4300iOpcode DelaySlot;
if (!g_MMU->MemoryValue32(m_CompilePC + 4, DelaySlot.Value))
{
g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD));
}
if (R4300iInstruction(m_CompilePC, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value) && (m_CompilePC & 0xFFC) != 0xFFC)
{ {
if (IsConst(m_Opcode.rs)) if (IsConst(m_Opcode.rs))
{ {
@ -4424,7 +4419,13 @@ void CX86RecompilerOps::SPECIAL_JALR()
} }
else if (m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT_DONE) else if (m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT_DONE)
{ {
if (DelaySlotEffectsCompare(m_CompilePC, m_Opcode.rs, 0)) R4300iOpcode DelaySlot;
if (!g_MMU->MemoryValue32(m_CompilePC + 4, DelaySlot.Value))
{
g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD));
}
if (R4300iInstruction(m_CompilePC, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value))
{ {
CompileExit(m_CompilePC, (uint32_t)-1, m_RegWorkingSet, CExitInfo::Normal, true, nullptr); CompileExit(m_CompilePC, (uint32_t)-1, m_RegWorkingSet, CExitInfo::Normal, true, nullptr);
} }

View File

@ -33,7 +33,7 @@ public:
// Branch functions // Branch functions
void Compile_BranchCompare(BRANCH_COMPARE CompareType); void Compile_BranchCompare(BRANCH_COMPARE CompareType);
void Compile_Branch(BRANCH_COMPARE CompareType, BRANCH_TYPE BranchType, bool Link); void Compile_Branch(BRANCH_COMPARE CompareType, bool Link);
void Compile_BranchLikely(BRANCH_COMPARE CompareType, bool Link); void Compile_BranchLikely(BRANCH_COMPARE CompareType, bool Link);
void BNE_Compare(); void BNE_Compare();
void BEQ_Compare(); void BEQ_Compare();