Fix handling of jalr when delay slot changes rd.

This commit is contained in:
Unknown W. Brackets 2013-11-13 23:44:15 -08:00
parent 26f5922174
commit 763eff181d
2 changed files with 20 additions and 14 deletions

View File

@ -461,23 +461,28 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
}
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
bool andLink = (op & 0x3f) == 9;
MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC + 4);
bool delaySlotIsNice = IsDelaySlotNiceReg(op, delaySlotOp, rs);
if (andLink && rs == rd)
delaySlotIsNice = false;
CONDITIONAL_NICE_DELAYSLOT;
ARMReg destReg = R8;
if (IsSyscall(delaySlotOp)) {
_dbg_assert_msg_(JIT, (op & 0x3f) == 8, "jalr followed by syscall not supported.");
gpr.MapReg(rs);
MovToPC(gpr.R(rs)); // For syscall to be able to return.
if (andLink)
gpr.SetImm(rd, js.compilerPC + 8);
CompileDelaySlot(DELAYSLOT_FLUSH);
return; // Syscall wrote exit code.
} else if (delaySlotIsNice) {
if (andLink)
gpr.SetImm(rd, js.compilerPC + 8);
CompileDelaySlot(DELAYSLOT_NICE);
if (rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) {
if (!andLink && rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) {
// According to the MIPS ABI, there are some regs we don't need to preserve.
// Let's discard them so we don't need to write them back.
// NOTE: Not all games follow the MIPS ABI! Tekken 6, for example, will crash
@ -492,9 +497,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
if (jo.continueJumps && gpr.IsImm(rs) && js.numInstructions < jo.continueMaxInstructions) {
// Account for the increment in the loop.
js.compilerPC = gpr.GetImm(rs) - 4;
if ((op & 0x3f) == 9) {
gpr.SetImm(rd, js.compilerPC + 8);
}
// In case the delay slot was a break or something.
js.compiling = true;
return;
@ -507,6 +509,8 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
// Delay slot - this case is very rare, might be able to free up R8.
gpr.MapReg(rs);
MOV(R8, gpr.R(rs));
if (andLink)
gpr.SetImm(rd, js.compilerPC + 8);
CompileDelaySlot(DELAYSLOT_NICE);
FlushAll();
}
@ -516,8 +520,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
case 8: //jr
break;
case 9: //jalr
gpr.SetRegImm(R0, js.compilerPC + 8);
STR(R0, CTXREG, (int)rd * 4);
break;
default:
_dbg_assert_msg_(CPU,0,"Trying to compile instruction that can't be compiled");

View File

@ -587,18 +587,21 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
}
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
bool andLink = (op & 0x3f) == 9;
MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC + 4);
bool delaySlotIsNice = IsDelaySlotNiceReg(op, delaySlotOp, rs);
if (andLink && rs == rd)
delaySlotIsNice = false;
CONDITIONAL_NICE_DELAYSLOT;
if (IsSyscall(delaySlotOp))
{
_dbg_assert_msg_(JIT, (op & 0x3f) == 8, "jalr followed by syscall not supported.");
// If this is a syscall, write the pc (for thread switching and other good reasons.)
gpr.MapReg(rs, true, false);
MOV(32, M(&currentMIPS->pc), gpr.R(rs));
if (andLink)
gpr.SetImm(rd, js.compilerPC + 8);
CompileDelaySlot(DELAYSLOT_FLUSH);
// Syscalls write the exit code for us.
@ -607,9 +610,11 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
}
else if (delaySlotIsNice)
{
if (andLink)
gpr.SetImm(rd, js.compilerPC + 8);
CompileDelaySlot(DELAYSLOT_NICE);
if (rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) {
if (!andLink && rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) {
// According to the MIPS ABI, there are some regs we don't need to preserve.
// Let's discard them so we don't need to write them back.
// NOTE: Not all games follow the MIPS ABI! Tekken 6, for example, will crash
@ -625,8 +630,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
{
// Account for the increment in the loop.
js.compilerPC = gpr.GetImm(rs) - 4;
if ((op & 0x3f) == 9)
gpr.SetImm(rd, js.compilerPC + 8);
// In case the delay slot was a break or something.
js.compiling = true;
return;
@ -640,6 +643,8 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
// Latch destination now - save it in memory.
gpr.MapReg(rs, true, false);
MOV(32, M(&savedPC), gpr.R(rs));
if (andLink)
gpr.SetImm(rd, js.compilerPC + 8);
CompileDelaySlot(DELAYSLOT_NICE);
MOV(32, R(EAX), M(&savedPC));
FlushAll();
@ -650,7 +655,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
case 8: //jr
break;
case 9: //jalr
MOV(32, M(&mips_->r[rd]), Imm32(js.compilerPC + 8));
break;
default:
_dbg_assert_msg_(CPU,0,"Trying to compile instruction that can't be compiled");