armjit: Handle NAN correctly in float conversion.

This commit is contained in:
Unknown W. Brackets 2014-06-29 20:05:59 -07:00
parent c168db5943
commit f339f7d539
2 changed files with 30 additions and 0 deletions

View File

@ -821,6 +821,14 @@ public:
MOVI2R(reg, (u32)(intptr_t)(void *)val);
}
void MOVIU2F(ARMReg dest, u32 val, ARMReg tempReg, bool negate = false) {
union {
u32 u;
float f;
} v = {val};
MOVI2F(dest, v.f, tempReg, negate);
}
void ADDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
bool TryADDI2R(ARMReg rd, ARMReg rs, u32 val);
void SUBI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);

View File

@ -284,7 +284,12 @@ void Jit::Comp_FPU2op(MIPSOpcode op) {
break;
case 13: //FsI(fd) = Rto0(F(fs))); break; //trunc.w.s
fpr.MapDirtyIn(fd, fs);
VCMP(fpr.R(fs), fpr.R(fs));
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED | ROUND_TO_ZERO);
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
SetCC(CC_VS);
MOVIU2F(fpr.R(fd), 0x7FFFFFFF, SCRATCHREG1);
SetCC(CC_AL);
break;
case 14: //FsI(fd) = (int)ceilf (F(fs)); break; //ceil.w.s
{
@ -300,6 +305,9 @@ void Jit::Comp_FPU2op(MIPSOpcode op) {
VADD(S1, S1, S0);
VCVT(fpr.R(fd), S1, TO_INT | IS_SIGNED | ROUND_TO_ZERO);
SetJumpTarget(skip);
SetCC(CC_VS);
MOVIU2F(fpr.R(fd), 0x7FFFFFFF, SCRATCHREG1);
SetCC(CC_AL);
break;
}
case 15: //FsI(fd) = (int)floorf(F(fs)); break; //floor.w.s
@ -316,6 +324,9 @@ void Jit::Comp_FPU2op(MIPSOpcode op) {
VSUB(S1, S1, S0);
VCVT(fpr.R(fd), S1, TO_INT | IS_SIGNED | ROUND_TO_ZERO);
SetJumpTarget(skip);
SetCC(CC_VS);
MOVIU2F(fpr.R(fd), 0x7FFFFFFF, SCRATCHREG1);
SetCC(CC_AL);
break;
}
case 32: //F(fd) = (float)FsI(fs); break; //cvt.s.w
@ -353,6 +364,9 @@ void Jit::Comp_FPU2op(MIPSOpcode op) {
MOVI2F(S0, 1.0f, SCRATCHREG1);
VADD(S1, S1, S0);
VCVT(fpr.R(fd), S1, TO_INT | IS_SIGNED | ROUND_TO_ZERO);
SetCC(CC_VS);
MOVIU2F(fpr.R(fd), 0x7FFFFFFF, SCRATCHREG1);
SetCC(CC_AL);
FixupBranch finishCeil2 = B();
// For floor, we subtract one if we ended up higher.
@ -362,15 +376,23 @@ void Jit::Comp_FPU2op(MIPSOpcode op) {
MOVI2F(S0, 1.0f, SCRATCHREG1);
VSUB(S1, S1, S0);
VCVT(fpr.R(fd), S1, TO_INT | IS_SIGNED | ROUND_TO_ZERO);
SetCC(CC_VS);
MOVIU2F(fpr.R(fd), 0x7FFFFFFF, SCRATCHREG1);
SetCC(CC_AL);
FixupBranch finishFloor2 = B();
SetJumpTarget(skipCeilFloor);
VCMP(fpr.R(fs), fpr.R(fs));
// LT 1 means 0, nearest. EQ means 1, round to zero.
SetCC(CC_LT);
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED);
SetCC(CC_EQ);
VCVT(fpr.R(fd), fpr.R(fs), TO_INT | IS_SIGNED | ROUND_TO_ZERO);
SetCC(CC_AL);
VMRS_APSR(); // Move FP flags from FPSCR to APSR (regular flags).
SetCC(CC_VS);
MOVIU2F(fpr.R(fd), 0x7FFFFFFF, SCRATCHREG1);
SetCC(CC_AL);
SetJumpTarget(finishCeil1);
SetJumpTarget(finishCeil2);