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:
parent
df35e95e57
commit
ea35eeb728
|
@ -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
|
||||
|
|
|
@ -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--;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue