Fix FTRC op in both interpreter and dynarec with respect to Inf and NaN

The -ffast-math gcc option implies the -ffinite-math-only option, which
produces wrong results with Inf and NaN. Use integer math to detect the
sign of float numbers in FTRC to avoid these issues.
Also the upper cut off value for conversion was apparently wrong.
Also fixed the x86 dynarec but not tested.
Fixes wrong car color in Tokyo Xtreme Racer car selection screen.
This commit is contained in:
Flyinghead 2018-07-13 12:02:32 +02:00
parent df35e95e57
commit ea35eeb728
3 changed files with 16 additions and 13 deletions

View File

@ -677,9 +677,10 @@ shil_opc(cvt_f2i_t)
shil_canonical
(
u32,f1,(f32 f1),
if (f1 > 0x7FFFFFBF)
f1 = 0x7FFFFFBF;
return (s32)f1;
if (f1 > 2147483520.0f) // IEEE 754: 0x4effffff
return 0x7fffffff;
else
return (s32)f1;
)
shil_compile
@ -687,7 +688,6 @@ shil_compile
shil_cf_arg_f32(rs1);
shil_cf(f1);
shil_cf_rv_u32(rd);
//die();
)
shil_opc_end()
@ -1044,4 +1044,4 @@ SHIL_END
#undef UN_OP_I
#undef UN_OP_F
#undef BIN_OP_FU
#undef shil_recimp
#undef shil_recimp

View File

@ -628,22 +628,25 @@ sh4op(i1111_nnnn_0011_1101)
if (fpscr.PR == 0)
{
u32 n = GetN(op);
fpul = (u32)(s32)min(fr[n],(float)0x7FFFFFBF);
fpul = (u32)(s32)min(fr[n], 2147483520.0f); // IEEE 754: 0x4effffff
if (fpul==0x80000000) //this is actually a x86-specific fix. I think ARM saturates
// Intel CPUs convert out of range float numbers to 0x80000000. Manually set the correct sign
if (fpul == 0x80000000)
{
if (fr[n]>0)
if (*(int *)&fr[n] > 0) // Using integer math to avoid issues with Inf and NaN
fpul--;
}
}
else
{
u32 n = (op >> 9) & 0x07;
fpul = (u32)(s32)GetDR(n);
f64 f = GetDR(n);
fpul = (u32)(s32)f;
if (fpul==0x80000000) //this is actually a x86-specific fix. I think ARM saturates
// Intel CPUs convert out of range float numbers to 0x80000000. Manually set the correct sign
if (fpul == 0x80000000)
{
if (GetDR(n)>0)
if (*(s64 *)&f > 0) // Using integer math to avoid issues with Inf and NaN
fpul--;
}
}

View File

@ -1453,7 +1453,7 @@ void ngen_opcode(RuntimeBlockInfo* block, shil_opcode* op,x86_block* x86e, bool
verify(op->rs1.is_r32f());
verify(reg.IsAllocg(op->rd));
verify(reg.IsAllocf(op->rs1));
static f32 sse_ftrc_saturate = 0x7FFFFFBF;//1.11111111111111111111111 << 31
static f32 sse_ftrc_saturate = 2147483520.0f; // IEEE 754: 0x4effffff
x86e->Emit(op_movaps, XMM0, reg.mapf(op->rs1));
x86e->Emit(op_minss, XMM0, &sse_ftrc_saturate);
x86e->Emit(op_cvttss2si, reg.mapg(op->rd), XMM0);
@ -1536,4 +1536,4 @@ defaulty:
}
}
#endif
#endif