CPU/NewRec: Enable delay slot swapping in more situations

Load delay is always updated, so don't need to swap when it's reading
from a delayed register. Branching on a delayed register will also be
fine, since it won't be flushed by the the branch executes.
This commit is contained in:
Stenzek 2024-05-19 23:55:53 +10:00
parent 09b43f962a
commit ab4c6f2dde
No known key found for this signature in database
1 changed files with 11 additions and 18 deletions

View File

@ -391,23 +391,22 @@ bool CPU::NewRec::Compiler::TrySwapDelaySlot(Reg rs, Reg rt, Reg rd)
case InstructionOp::lbu: case InstructionOp::lbu:
case InstructionOp::lhu: case InstructionOp::lhu:
case InstructionOp::lwr: case InstructionOp::lwr:
case InstructionOp::sb:
case InstructionOp::sh:
case InstructionOp::swl:
case InstructionOp::sw:
case InstructionOp::swr:
{ {
if ((rs != Reg::zero && rs == opcode_rt) || (rt != Reg::zero && rt == opcode_rt) || if ((rs != Reg::zero && rs == opcode_rt) || (rt != Reg::zero && rt == opcode_rt) ||
(rd != Reg::zero && (rd == opcode_rs || rd == opcode_rt)) || (rd != Reg::zero && (rd == opcode_rs || rd == opcode_rt)))
(HasLoadDelay() && (m_load_delay_register == opcode_rs || m_load_delay_register == opcode_rt)))
{ {
goto is_unsafe; goto is_unsafe;
} }
} }
break; break;
case InstructionOp::lwc2: // LWC2 case InstructionOp::sb:
case InstructionOp::swc2: // SWC2 case InstructionOp::sh:
case InstructionOp::swl:
case InstructionOp::sw:
case InstructionOp::swr:
case InstructionOp::lwc2:
case InstructionOp::swc2:
break; break;
case InstructionOp::funct: // SPECIAL case InstructionOp::funct: // SPECIAL
@ -432,9 +431,7 @@ bool CPU::NewRec::Compiler::TrySwapDelaySlot(Reg rs, Reg rt, Reg rd)
case InstructionFunct::sltu: case InstructionFunct::sltu:
{ {
if ((rs != Reg::zero && rs == opcode_rd) || (rt != Reg::zero && rt == opcode_rd) || if ((rs != Reg::zero && rs == opcode_rd) || (rt != Reg::zero && rt == opcode_rd) ||
(rd != Reg::zero && (rd == opcode_rs || rd == opcode_rt)) || (rd != Reg::zero && (rd == opcode_rs || rd == opcode_rt)))
(HasLoadDelay() && (m_load_delay_register == opcode_rs || m_load_delay_register == opcode_rt ||
m_load_delay_register == opcode_rd)))
{ {
goto is_unsafe; goto is_unsafe;
} }
@ -445,11 +442,7 @@ bool CPU::NewRec::Compiler::TrySwapDelaySlot(Reg rs, Reg rt, Reg rd)
case InstructionFunct::multu: case InstructionFunct::multu:
case InstructionFunct::div: case InstructionFunct::div:
case InstructionFunct::divu: case InstructionFunct::divu:
{ break;
if (HasLoadDelay() && (m_load_delay_register == opcode_rs || m_load_delay_register == opcode_rt))
goto is_unsafe;
}
break;
default: default:
goto is_unsafe; goto is_unsafe;
@ -470,7 +463,7 @@ bool CPU::NewRec::Compiler::TrySwapDelaySlot(Reg rs, Reg rt, Reg rd)
case CopCommonInstruction::cfcn: // CFC0 case CopCommonInstruction::cfcn: // CFC0
{ {
if ((rs != Reg::zero && rs == opcode_rt) || (rt != Reg::zero && rt == opcode_rt) || if ((rs != Reg::zero && rs == opcode_rt) || (rt != Reg::zero && rt == opcode_rt) ||
(rd != Reg::zero && rd == opcode_rt) || (HasLoadDelay() && m_load_delay_register == opcode_rt)) (rd != Reg::zero && rd == opcode_rt))
{ {
goto is_unsafe; goto is_unsafe;
} }