Merge pull request #6812 from unknownbrackets/jit-minor

Correctly handle flags/temp regs when setting rounding mode
This commit is contained in:
Henrik Rydgård 2014-08-31 09:30:51 +02:00
commit c02f1ca3e1
5 changed files with 43 additions and 34 deletions

View file

@ -558,8 +558,8 @@ void Jit::Comp_Syscall(MIPSOpcode op)
gpr.SetRegImm(R0, op.encoding);
QuickCallFunction(R1, (void *)&CallSyscall);
}
RestoreDowncount();
SetRoundingMode();
RestoreDowncount();
WriteSyscallExit();
js.compiling = false;

View file

@ -50,7 +50,6 @@ namespace MIPSComp
void Jit::Comp_FPU3op(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
SetRoundingMode();
int ft = _FT;
int fs = _FS;
@ -191,8 +190,6 @@ void Jit::Comp_FPULS(MIPSOpcode op)
void Jit::Comp_FPUComp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
// TODO: Does this matter here?
SetRoundingMode();
int opc = op & 0xF;
if (opc >= 8) opc -= 8; // alias
@ -338,7 +335,6 @@ void Jit::Comp_FPU2op(MIPSOpcode op) {
break;
case 36: //FsI(fd) = (int) F(fs); break; //cvt.w.s
fpr.MapDirtyIn(fd, fs);
SetRoundingMode();
VCMP(fpr.R(fs), fpr.R(fs));
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED);
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
@ -410,23 +406,7 @@ void Jit::Comp_mxc1(MIPSOpcode op)
} else {
gpr.MapDirtyIn(MIPS_REG_FPCOND, rt);
}
// Hardware rounding method.
// Left here in case it is faster than conditional method.
/*
AND(SCRATCHREG1, gpr.R(rt), Operand2(3));
// MIPS Rounding Mode <-> ARM Rounding Mode
// 0, 1, 2, 3 <-> 0, 3, 1, 2
CMP(SCRATCHREG1, Operand2(1));
SetCC(CC_EQ); ADD(SCRATCHREG1, SCRATCHREG1, Operand2(2));
SetCC(CC_GT); SUB(SCRATCHREG1, SCRATCHREG1, Operand2(1));
SetCC(CC_AL);
// Load and Store RM to FPSCR
VMRS(SCRATCHREG2);
BIC(SCRATCHREG2, SCRATCHREG2, Operand2(0x3 << 22));
ORR(SCRATCHREG2, SCRATCHREG2, Operand2(SCRATCHREG1, ST_LSL, 22));
VMSR(SCRATCHREG2);
*/
// Update MIPS state
// TODO: Technically, should mask by 0x0181FFFF. Maybe just put all of FCR31 in the reg?
STR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31));
@ -437,6 +417,14 @@ void Jit::Comp_mxc1(MIPSOpcode op)
MOV(SCRATCHREG1, Operand2(gpr.R(rt), ST_LSR, 23));
AND(gpr.R(MIPS_REG_FPCOND), SCRATCHREG1, Operand2(1));
#endif
SetRoundingMode();
} else {
if ((gpr.GetImm(rt) & 3) == 0) {
// Default nearest mode, let's do this the fast way.
ClearRoundingMode();
} else {
SetRoundingMode();
}
}
} else {
Comp_Generic(op);

View file

@ -381,12 +381,14 @@ bool Jit::ReplaceJalTo(u32 dest) {
gpr.SetImm(MIPS_REG_RA, js.compilerPC + 8);
CompileDelaySlot(DELAYSLOT_NICE);
FlushAll();
ClearRoundingMode();
if (BLInRange((const void *)(entry->replaceFunc))) {
BL((const void *)(entry->replaceFunc));
} else {
MOVI2R(R0, (u32)entry->replaceFunc);
BL(R0);
}
SetRoundingMode();
WriteDownCountR(R0);
}
@ -433,6 +435,7 @@ void Jit::Comp_ReplacementFunc(MIPSOpcode op)
}
} else if (entry->replaceFunc) {
FlushAll();
ClearRoundingMode();
gpr.SetRegImm(SCRATCHREG1, js.compilerPC);
MovToPC(SCRATCHREG1);
@ -447,8 +450,10 @@ void Jit::Comp_ReplacementFunc(MIPSOpcode op)
if (entry->flags & (REPFLAG_HOOKENTER | REPFLAG_HOOKEXIT)) {
// Compile the original instruction at this address. We ignore cycles for hooks.
SetRoundingMode();
MIPSCompileOp(Memory::Read_Instruction(js.compilerPC, true));
} else {
SetRoundingMode();
LDR(R1, CTXREG, MIPS_REG_RA * 4);
WriteDownCountR(R0);
WriteExitDestInR(R1);
@ -550,31 +555,37 @@ void Jit::ClearRoundingMode()
{
VMRS(SCRATCHREG2);
// Assume we're always in round-to-nearest mode beforehand.
BIC(SCRATCHREG1, SCRATCHREG2, AssumeMakeOperand2(3 << 22));
VMSR(SCRATCHREG1);
BIC(SCRATCHREG2, SCRATCHREG2, AssumeMakeOperand2(3 << 22));
VMSR(SCRATCHREG2);
}
}
void Jit::SetRoundingMode()
{
// NOTE: Must not destory R0.
if (g_Config.bSetRoundingMode)
{
LDR(SCRATCHREG1, CTXREG, offsetof(MIPSState, fcr31));
AND(SCRATCHREG1, SCRATCHREG1, Operand2(3));
LDR(SCRATCHREG2, CTXREG, offsetof(MIPSState, fcr31));
AND(SCRATCHREG2, SCRATCHREG2, Operand2(3));
// MIPS Rounding Mode: ARM Rounding Mode
// 0: Round nearest 0
// 1: Round to zero 3
// 2: Round up (ceil) 1
// 3: Round down (floor) 2
CMP(SCRATCHREG1, Operand2(1));
SetCC(CC_EQ); ADD(SCRATCHREG1, SCRATCHREG1, Operand2(2));
SetCC(CC_GT); SUB(SCRATCHREG1, SCRATCHREG1, Operand2(1));
CMP(SCRATCHREG2, Operand2(1));
FixupBranch skip = B_CC(CC_LT);
SetCC(CC_EQ); ADD(SCRATCHREG2, SCRATCHREG2, Operand2(2));
SetCC(CC_GT); SUB(SCRATCHREG2, SCRATCHREG2, Operand2(1));
SetCC(CC_AL);
VMRS(SCRATCHREG2);
PUSH(1, SCRATCHREG1);
VMRS(SCRATCHREG1);
// Assume we're always in round-to-nearest mode beforehand.
ORR(SCRATCHREG1, SCRATCHREG2, Operand2(SCRATCHREG1, ST_LSL, 22));
VMSR(SCRATCHREG1);
ORR(SCRATCHREG2, SCRATCHREG2, Operand2(SCRATCHREG1, ST_LSL, 22));
VMSR(SCRATCHREG2);
POP(1, SCRATCHREG1);
SetJumpTarget(skip);
}
}

View file

@ -383,6 +383,12 @@ void Jit::Comp_mxc1(MIPSOpcode op)
if (gpr.IsImm(rt)) {
gpr.SetImm(MIPS_REG_FPCOND, (gpr.GetImm(rt) >> 23) & 1);
MOV(32, M(&mips_->fcr31), Imm32(gpr.GetImm(rt) & 0x0181FFFF));
if ((gpr.GetImm(rt) & 3) == 0) {
// Default nearest mode, let's do this the fast way.
ClearRoundingMode();
} else {
SetRoundingMode();
}
} else {
gpr.Lock(rt, MIPS_REG_FPCOND);
gpr.MapReg(rt, true, false);
@ -393,6 +399,7 @@ void Jit::Comp_mxc1(MIPSOpcode op)
MOV(32, M(&mips_->fcr31), gpr.R(rt));
AND(32, M(&mips_->fcr31), Imm32(0x0181FFFF));
gpr.UnlockAll();
SetRoundingMode();
}
} else {
Comp_Generic(op);

View file

@ -487,8 +487,8 @@ bool Jit::ReplaceJalTo(u32 dest) {
MOV(32, M(&mips_->pc), Imm32(js.compilerPC));
ClearRoundingMode();
ABI_CallFunction(entry->replaceFunc);
SetRoundingMode();
SUB(32, M(&currentMIPS->downcount), R(EAX));
SetRoundingMode();
}
js.compilerPC += 4;
@ -539,14 +539,16 @@ void Jit::Comp_ReplacementFunc(MIPSOpcode op)
MOV(32, M(&mips_->pc), Imm32(js.compilerPC));
ClearRoundingMode();
ABI_CallFunction(entry->replaceFunc);
SetRoundingMode();
if (entry->flags & (REPFLAG_HOOKENTER | REPFLAG_HOOKEXIT)) {
// Compile the original instruction at this address. We ignore cycles for hooks.
SetRoundingMode();
MIPSCompileOp(Memory::Read_Instruction(js.compilerPC, true));
} else {
MOV(32, R(ECX), M(&currentMIPS->r[MIPS_REG_RA]));
SUB(32, M(&currentMIPS->downcount), R(EAX));
SetRoundingMode();
SUB(32, M(&currentMIPS->downcount), Imm8(0));
WriteExitDestInReg(ECX);
js.compiling = false;
}
@ -694,17 +696,18 @@ bool Jit::CheckJitBreakpoint(u32 addr, int downcountOffset)
MOV(32, M(&mips_->pc), Imm32(js.compilerPC));
ClearRoundingMode();
ABI_CallFunction(&JitBreakpoint);
SetRoundingMode();
// If 0, the conditional breakpoint wasn't taken.
CMP(32, R(EAX), Imm32(0));
FixupBranch skip = J_CC(CC_Z);
WriteDowncount(downcountOffset);
// Just to fix the stack.
SetRoundingMode();
LOAD_FLAGS;
JMP(asm_.dispatcherCheckCoreState, true);
SetJumpTarget(skip);
SetRoundingMode();
LOAD_FLAGS;
return true;