mirror of https://github.com/RPCS3/rpcs3.git
Fix lfs/stfs with SNaNs.
This commit is contained in:
parent
42b55c60e7
commit
b7761beee9
|
@ -3059,7 +3059,16 @@ private:
|
||||||
void LFSX(u32 frd, u32 ra, u32 rb)
|
void LFSX(u32 frd, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||||
CPU.FPR[frd] = vm::get_ref<be_t<float>>(vm::cast(addr)).value();
|
float val = vm::get_ref<be_t<float>>(vm::cast(addr)).value();
|
||||||
|
if (!FPRdouble::IsNaN(val))
|
||||||
|
{
|
||||||
|
CPU.FPR[frd] = val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 bits = (u32&)val;
|
||||||
|
(u64&)CPU.FPR[frd] = (bits & 0x80000000) << 32 | 7ULL << 60 | (bits & 0x7fffffff) << 29;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void SRW(u32 ra, u32 rs, u32 rb, bool rc)
|
void SRW(u32 ra, u32 rs, u32 rb, bool rc)
|
||||||
{
|
{
|
||||||
|
@ -3120,7 +3129,16 @@ private:
|
||||||
void LFSUX(u32 frd, u32 ra, u32 rb)
|
void LFSUX(u32 frd, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
const u64 addr = CPU.GPR[ra] + CPU.GPR[rb];
|
const u64 addr = CPU.GPR[ra] + CPU.GPR[rb];
|
||||||
CPU.FPR[frd] = vm::get_ref<be_t<float>>(vm::cast(addr)).value();
|
float val = vm::get_ref<be_t<float>>(vm::cast(addr)).value();
|
||||||
|
if (!FPRdouble::IsNaN(val))
|
||||||
|
{
|
||||||
|
CPU.FPR[frd] = val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 bits = (u32&)val;
|
||||||
|
(u64&)CPU.FPR[frd] = (bits & 0x80000000) << 32 | 7ULL << 60 | (bits & 0x7fffffff) << 29;
|
||||||
|
}
|
||||||
CPU.GPR[ra] = addr;
|
CPU.GPR[ra] = addr;
|
||||||
}
|
}
|
||||||
void SYNC(u32 l)
|
void SYNC(u32 l)
|
||||||
|
@ -3176,7 +3194,17 @@ private:
|
||||||
void STFSX(u32 frs, u32 ra, u32 rb)
|
void STFSX(u32 frs, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||||
vm::get_ref<be_t<float>>(vm::cast(addr)) = (float)CPU.FPR[frs];
|
double val = CPU.FPR[frs];
|
||||||
|
if (!FPRdouble::IsNaN(val))
|
||||||
|
{
|
||||||
|
vm::get_ref<be_t<float>>(vm::cast(addr)) = (float)val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 bits = (u64&)val;
|
||||||
|
u32 bits32 = (bits>>32 & 0x80000000) | (bits>>29 & 0x7fffffff);
|
||||||
|
vm::get_ref<be_t<u32>>(vm::cast(addr)) = (float)bits32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void STVRX(u32 vs, u32 ra, u32 rb)
|
void STVRX(u32 vs, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
|
@ -3188,7 +3216,17 @@ private:
|
||||||
void STFSUX(u32 frs, u32 ra, u32 rb)
|
void STFSUX(u32 frs, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
const u64 addr = CPU.GPR[ra] + CPU.GPR[rb];
|
const u64 addr = CPU.GPR[ra] + CPU.GPR[rb];
|
||||||
vm::get_ref<be_t<float>>(vm::cast(addr)) = (float)CPU.FPR[frs];
|
double val = CPU.FPR[frs];
|
||||||
|
if (!FPRdouble::IsNaN(val))
|
||||||
|
{
|
||||||
|
vm::get_ref<be_t<float>>(vm::cast(addr)) = (float)val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 bits = (u64&)val;
|
||||||
|
u32 bits32 = (bits>>32 & 0x80000000) | (bits>>29 & 0x7fffffff);
|
||||||
|
vm::get_ref<be_t<u32>>(vm::cast(addr)) = (float)bits32;
|
||||||
|
}
|
||||||
CPU.GPR[ra] = addr;
|
CPU.GPR[ra] = addr;
|
||||||
}
|
}
|
||||||
void STSWI(u32 rd, u32 ra, u32 nb)
|
void STSWI(u32 rd, u32 ra, u32 nb)
|
||||||
|
@ -3459,12 +3497,30 @@ private:
|
||||||
void LFS(u32 frd, u32 ra, s32 d)
|
void LFS(u32 frd, u32 ra, s32 d)
|
||||||
{
|
{
|
||||||
const u64 addr = ra ? CPU.GPR[ra] + d : d;
|
const u64 addr = ra ? CPU.GPR[ra] + d : d;
|
||||||
CPU.FPR[frd] = vm::get_ref<be_t<float>>(vm::cast(addr)).value();
|
float val = vm::get_ref<be_t<float>>(vm::cast(addr)).value();
|
||||||
|
if (!FPRdouble::IsNaN(val))
|
||||||
|
{
|
||||||
|
CPU.FPR[frd] = val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 bits = (u32&)val;
|
||||||
|
(u64&)CPU.FPR[frd] = (bits & 0x80000000) << 32 | 7ULL << 60 | (bits & 0x7fffffff) << 29;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void LFSU(u32 frd, u32 ra, s32 ds)
|
void LFSU(u32 frd, u32 ra, s32 ds)
|
||||||
{
|
{
|
||||||
const u64 addr = CPU.GPR[ra] + ds;
|
const u64 addr = CPU.GPR[ra] + ds;
|
||||||
CPU.FPR[frd] = vm::get_ref<be_t<float>>(vm::cast(addr)).value();
|
float val = vm::get_ref<be_t<float>>(vm::cast(addr)).value();
|
||||||
|
if (!FPRdouble::IsNaN(val))
|
||||||
|
{
|
||||||
|
CPU.FPR[frd] = val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 bits = (u32&)val;
|
||||||
|
(u64&)CPU.FPR[frd] = (bits & 0x80000000) << 32 | 7ULL << 60 | (bits & 0x7fffffff) << 29;
|
||||||
|
}
|
||||||
CPU.GPR[ra] = addr;
|
CPU.GPR[ra] = addr;
|
||||||
}
|
}
|
||||||
void LFD(u32 frd, u32 ra, s32 d)
|
void LFD(u32 frd, u32 ra, s32 d)
|
||||||
|
@ -3481,12 +3537,32 @@ private:
|
||||||
void STFS(u32 frs, u32 ra, s32 d)
|
void STFS(u32 frs, u32 ra, s32 d)
|
||||||
{
|
{
|
||||||
const u64 addr = ra ? CPU.GPR[ra] + d : d;
|
const u64 addr = ra ? CPU.GPR[ra] + d : d;
|
||||||
vm::get_ref<be_t<float>>(vm::cast(addr)) = (float)CPU.FPR[frs];
|
double val = CPU.FPR[frs];
|
||||||
|
if (!FPRdouble::IsNaN(val))
|
||||||
|
{
|
||||||
|
vm::get_ref<be_t<float>>(vm::cast(addr)) = (float)val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 bits = (u64&)val;
|
||||||
|
u32 bits32 = (bits>>32 & 0x80000000) | (bits>>29 & 0x7fffffff);
|
||||||
|
vm::get_ref<be_t<u32>>(vm::cast(addr)) = (float)bits32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void STFSU(u32 frs, u32 ra, s32 d)
|
void STFSU(u32 frs, u32 ra, s32 d)
|
||||||
{
|
{
|
||||||
const u64 addr = CPU.GPR[ra] + d;
|
const u64 addr = CPU.GPR[ra] + d;
|
||||||
vm::get_ref<be_t<float>>(vm::cast(addr)) = (float)CPU.FPR[frs];
|
double val = CPU.FPR[frs];
|
||||||
|
if (!FPRdouble::IsNaN(val))
|
||||||
|
{
|
||||||
|
vm::get_ref<be_t<float>>(vm::cast(addr)) = (float)val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 bits = (u64&)val;
|
||||||
|
u32 bits32 = (bits>>32 & 0x80000000) | (bits>>29 & 0x7fffffff);
|
||||||
|
vm::get_ref<be_t<u32>>(vm::cast(addr)) = (float)bits32;
|
||||||
|
}
|
||||||
CPU.GPR[ra] = addr;
|
CPU.GPR[ra] = addr;
|
||||||
}
|
}
|
||||||
void STFD(u32 frs, u32 ra, s32 d)
|
void STFD(u32 frs, u32 ra, s32 d)
|
||||||
|
|
|
@ -443,18 +443,22 @@ struct PPCdouble
|
||||||
|
|
||||||
PPCdouble() : _u64(0)
|
PPCdouble() : _u64(0)
|
||||||
{
|
{
|
||||||
|
type = UpdateType();
|
||||||
}
|
}
|
||||||
|
|
||||||
PPCdouble(double val) : _double(val)
|
PPCdouble(double val) : _double(val)
|
||||||
{
|
{
|
||||||
|
type = UpdateType();
|
||||||
}
|
}
|
||||||
|
|
||||||
PPCdouble(u64 val) : _u64(val)
|
PPCdouble(u64 val) : _u64(val)
|
||||||
{
|
{
|
||||||
|
type = UpdateType();
|
||||||
}
|
}
|
||||||
|
|
||||||
PPCdouble(u32 val) : _u64(val)
|
PPCdouble(u32 val) : _u64(val)
|
||||||
{
|
{
|
||||||
|
type = UpdateType();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue