diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp index 0a9385e62..b2a9c8923 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp @@ -18,200 +18,6 @@ void ExecuteInterpreterOps(uint32_t /*Cycles*/) 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() { R4300iOp::m_TestTimer = false; diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp index 31122b05c..f82f5b599 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp @@ -700,8 +700,6 @@ R4300iOp::Func * R4300iOp::BuildInterpreter() return Jump_Opcode; } -bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2); - // Opcode functions void R4300iOp::J() @@ -734,7 +732,8 @@ void R4300iOp::BEQ() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -754,7 +753,8 @@ void R4300iOp::BNE() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -774,7 +774,8 @@ void R4300iOp::BLEZ() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -794,7 +795,8 @@ void R4300iOp::BGTZ() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -895,7 +897,8 @@ void R4300iOp::BEQL() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -916,7 +919,8 @@ void R4300iOp::BNEL() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -937,7 +941,8 @@ void R4300iOp::BLEZL() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -958,7 +963,8 @@ void R4300iOp::BGTZL() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -1660,9 +1666,10 @@ void R4300iOp::REGIMM_BLTZ() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; 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; 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; 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; 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; } } - 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; } } } diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp index 163c49dc4..adc199e56 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp @@ -4,12 +4,11 @@ #include #include #include +#include #include #include #include -bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2); - #define TEST_COP1_USABLE_EXCEPTION \ if ((g_Reg->STATUS_REGISTER & STATUS_CU1) == 0) {\ 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; 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; } @@ -652,7 +652,8 @@ void R4300iOp32::BNE() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -672,7 +673,8 @@ void R4300iOp32::BLEZ() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -692,7 +694,8 @@ void R4300iOp32::BGTZ() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -793,7 +796,8 @@ void R4300iOp32::BEQL() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -814,7 +818,8 @@ void R4300iOp32::BNEL() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -835,7 +840,8 @@ void R4300iOp32::BLEZL() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -856,7 +862,8 @@ void R4300iOp32::BGTZL() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; } @@ -1075,9 +1082,10 @@ void R4300iOp32::REGIMM_BLTZ() g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; 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; 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; 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; 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; 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; } } - 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; } } } diff --git a/Source/Project64-core/N64System/Mips/R4300iInstruction.cpp b/Source/Project64-core/N64System/Mips/R4300iInstruction.cpp index fc1ef11fb..adadca79a 100644 --- a/Source/Project64-core/N64System/Mips/R4300iInstruction.cpp +++ b/Source/Project64-core/N64System/Mips/R4300iInstruction.cpp @@ -77,6 +77,253 @@ bool R4300iInstruction::HasDelaySlot(void) const 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) { if (COP1OpCode == R4300i_COP1_S) { return "S"; }; diff --git a/Source/Project64-core/N64System/Mips/R4300iInstruction.h b/Source/Project64-core/N64System/Mips/R4300iInstruction.h index 2864910b3..a47a3e1b5 100644 --- a/Source/Project64-core/N64System/Mips/R4300iInstruction.h +++ b/Source/Project64-core/N64System/Mips/R4300iInstruction.h @@ -12,6 +12,7 @@ public: std::string NameAndParam(); bool HasDelaySlot(void) const; + bool DelaySlotEffectsCompare(uint32_t DelayInstruction) const; private: R4300iInstruction(void); diff --git a/Source/Project64-core/N64System/Recompiler/CodeBlock.cpp b/Source/Project64-core/N64System/Recompiler/CodeBlock.cpp index 827e74425..0a985a0ad 100644 --- a/Source/Project64-core/N64System/Recompiler/CodeBlock.cpp +++ b/Source/Project64-core/N64System/Recompiler/CodeBlock.cpp @@ -8,8 +8,6 @@ #include #include -bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2); - #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) */ 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 { - 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; } @@ -519,7 +523,12 @@ bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t & } 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; } @@ -537,7 +546,12 @@ bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t & TargetPC = PC + ((int16_t)Command.offset << 2) + 4; 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; } @@ -583,8 +597,12 @@ bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t & { ContinuePC = PC + 8; } - - if (TargetPC == PC && !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 (TargetPC == PC && !R4300iInstruction(PC, Command.Value).DelaySlotEffectsCompare(DelaySlot.Value)) { PermLoop = true; } @@ -603,7 +621,12 @@ bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t & { 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; } @@ -701,7 +724,12 @@ bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t & TargetPC = PC + ((int16_t)Command.offset << 2) + 4; 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; } @@ -720,7 +748,12 @@ bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t & ContinuePC = PC + 8; 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; } diff --git a/Source/Project64-core/N64System/Recompiler/CodeSection.cpp b/Source/Project64-core/N64System/Recompiler/CodeSection.cpp index 4de0b16b6..1b4e4c66a 100644 --- a/Source/Project64-core/N64System/Recompiler/CodeSection.cpp +++ b/Source/Project64-core/N64System/Recompiler/CodeSection.cpp @@ -13,94 +13,6 @@ #include #include -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) : m_BlockInfo(CodeBlock), m_SectionID(ID), @@ -148,7 +60,10 @@ void CCodeSection::GenerateSectionLinkage() // Handle permanent loop 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()); } @@ -480,12 +395,12 @@ bool CCodeSection::GenerateNativeCode(uint32_t Test) case R4300i_REGIMM: switch (Opcode.rt) { - case R4300i_REGIMM_BLTZ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBLTZ, CRecompilerOps::BranchTypeRs, false); break; - case R4300i_REGIMM_BGEZ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBGEZ, 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, 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_BLTZAL: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBLTZ, CRecompilerOps::BranchTypeRs, true); break; - case R4300i_REGIMM_BGEZAL: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBGEZ, 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, true); 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_TGEI: m_RecompilerOps->Compile_TrapCompare(CRecompilerOps::TRAP_COMPARE::CompareTypeTGEI); break; @@ -496,10 +411,10 @@ bool CCodeSection::GenerateNativeCode(uint32_t Test) m_RecompilerOps->UnknownOpcode(); break; } break; - case R4300i_BEQ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBEQ, CRecompilerOps::BranchTypeRsRt, false); break; - case R4300i_BNE: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBNE, CRecompilerOps::BranchTypeRsRt, false); break; - case R4300i_BGTZ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBGTZ, CRecompilerOps::BranchTypeRs, false); break; - case R4300i_BLEZ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBLEZ, CRecompilerOps::BranchTypeRs, false); break; + case R4300i_BEQ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBEQ, false); break; + case R4300i_BNE: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBNE, false); break; + case R4300i_BGTZ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBGTZ, false); break; + case R4300i_BLEZ: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeBLEZ, false); break; case R4300i_J: m_RecompilerOps->J(); break; case R4300i_JAL: m_RecompilerOps->JAL(); break; case R4300i_ADDI: m_RecompilerOps->ADDI(); break; @@ -546,8 +461,8 @@ bool CCodeSection::GenerateNativeCode(uint32_t Test) case R4300i_COP1_BC: switch (Opcode.ft) { - case R4300i_COP1_BC_BCF: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeCOP1BCF, CRecompilerOps::BranchTypeCop1, false); break; - case R4300i_COP1_BC_BCT: m_RecompilerOps->Compile_Branch(CRecompilerOps::CompareTypeCOP1BCT, 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, 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; default: diff --git a/Source/Project64-core/N64System/Recompiler/LoopAnalysis.cpp b/Source/Project64-core/N64System/Recompiler/LoopAnalysis.cpp index 4b9bd40ab..f90112310 100644 --- a/Source/Project64-core/N64System/Recompiler/LoopAnalysis.cpp +++ b/Source/Project64-core/N64System/Recompiler/LoopAnalysis.cpp @@ -13,8 +13,6 @@ #define CHECKED_BUILD 1 #endif -bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2); - LoopAnalysis::LoopAnalysis(CCodeBlock * CodeBlock, CCodeSection * Section) : m_EnterSection(Section), m_BlockInfo(CodeBlock), @@ -261,7 +259,10 @@ bool LoopAnalysis::CheckLoopRegisterUsage(CCodeSection * Section) } 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__); } @@ -291,7 +292,10 @@ bool LoopAnalysis::CheckLoopRegisterUsage(CCodeSection * Section) }*/ 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__); } @@ -351,7 +355,10 @@ bool LoopAnalysis::CheckLoopRegisterUsage(CCodeSection * Section) } 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__); } @@ -380,7 +387,10 @@ bool LoopAnalysis::CheckLoopRegisterUsage(CCodeSection * Section) } 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__); } @@ -562,7 +572,10 @@ bool LoopAnalysis::CheckLoopRegisterUsage(CCodeSection * Section) }*/ 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__); } diff --git a/Source/Project64-core/N64System/Recompiler/RecompilerOps.h b/Source/Project64-core/N64System/Recompiler/RecompilerOps.h index d91f1e6c3..c3425a639 100644 --- a/Source/Project64-core/N64System/Recompiler/RecompilerOps.h +++ b/Source/Project64-core/N64System/Recompiler/RecompilerOps.h @@ -45,7 +45,7 @@ public: virtual void Compile_TrapCompare(TRAP_COMPARE CompareType) = 0; // 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; // Opcode functions diff --git a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp index 6746da065..193a40ad7 100644 --- a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp @@ -364,8 +364,6 @@ void CX86RecompilerOps::CompileWriteTLBMiss(x86Reg AddressReg, x86Reg LookUpReg) CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::TLBWriteMiss, false, JeLabel32); } -bool DelaySlotEffectsCompare(uint32_t PC, uint32_t Reg1, uint32_t Reg2); - // Trap functions 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 bool EffectDelaySlot; @@ -480,33 +478,12 @@ void CX86RecompilerOps::Compile_Branch(BRANCH_COMPARE CompareType, BRANCH_TYPE B 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; - 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"); } + g_Notify->FatalError(GS(MSG_FAIL_LOAD_WORD)); } + EffectDelaySlot = R4300iInstruction(m_CompilePC, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value); } else { @@ -4323,7 +4300,13 @@ void CX86RecompilerOps::SPECIAL_JR() m_Section->m_Cont.LinkLocation = 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)) { @@ -4342,7 +4325,13 @@ void CX86RecompilerOps::SPECIAL_JR() } 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); } @@ -4379,7 +4368,13 @@ void CX86RecompilerOps::SPECIAL_JALR() { 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)) { @@ -4424,7 +4419,13 @@ void CX86RecompilerOps::SPECIAL_JALR() } 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); } diff --git a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.h b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.h index 12949a30f..6efe85913 100644 --- a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.h +++ b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.h @@ -33,7 +33,7 @@ public: // Branch functions 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 BNE_Compare(); void BEQ_Compare();