diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index 2c1b0f7076..66ce49a8b0 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -231,3 +231,33 @@ inline u32 ConvertToSingleFTZ(u64 x) return (x >> 32) & 0x80000000; } } + +inline u64 ConvertToDouble(u32 _x) +{ + u64 x = _x; + u64 exp = (x >> 23) & 0xff; + u64 frac = x & 0x007fffff; + if (exp || frac == 0) + { + // not denormalized + u64 y = exp & 0x80; + u64 z = y << 54 | y << 53 | y << 52; + if (exp > 0 && exp < 255) + { + // not inf/nan/zero + z = ~z; + } + return ((x & 0xc0000000) << 32) | z | ((x & 0x3fffffff) << 29); + } + else + { + // denormalized + exp = 1023 - 126; + do + { + frac <<= 1; + exp -= 1; + } while ((frac & 0x00800000) == 0); + return ((x & 0x80000000) << 32) | (exp << 52) | ((frac & 0x007fffff) << 29); + } +} diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp index 3fb441f5b9..0356bd4247 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -93,9 +93,9 @@ void Interpreter::lfs(UGeckoInstruction _inst) u32 uTemp = Memory::Read_U32(Helper_Get_EA(_inst)); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { - double value = *(float*)&uTemp; - rPS0(_inst.FD) = value; - rPS1(_inst.FD) = value; + u64 value = ConvertToDouble(uTemp); + riPS0(_inst.FD) = value; + riPS1(_inst.FD) = value; } } @@ -105,9 +105,9 @@ void Interpreter::lfsu(UGeckoInstruction _inst) u32 uTemp = Memory::Read_U32(uAddress); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { - double value = *(float*)&uTemp; - rPS0(_inst.FD) = value; - rPS1(_inst.FD) = value; + u64 value = ConvertToDouble(uTemp); + riPS0(_inst.FD) = value; + riPS1(_inst.FD) = value; m_GPR[_inst.RA] = uAddress; } @@ -119,9 +119,9 @@ void Interpreter::lfsux(UGeckoInstruction _inst) u32 uTemp = Memory::Read_U32(uAddress); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { - double value = *(float*)&uTemp; - rPS0(_inst.FD) = value; - rPS1(_inst.FD) = value; + u64 value = ConvertToDouble(uTemp); + riPS0(_inst.FD) = value; + riPS1(_inst.FD) = value; m_GPR[_inst.RA] = uAddress; } } @@ -131,9 +131,9 @@ void Interpreter::lfsx(UGeckoInstruction _inst) u32 uTemp = Memory::Read_U32(Helper_Get_EA_X(_inst)); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { - double value = *(float*)&uTemp; - rPS0(_inst.FD) = value; - rPS1(_inst.FD) = value; + u64 value = ConvertToDouble(uTemp); + riPS0(_inst.FD) = value; + riPS1(_inst.FD) = value; } } @@ -282,9 +282,6 @@ void Interpreter::stfdu(UGeckoInstruction _inst) void Interpreter::stfs(UGeckoInstruction _inst) { - //double value = rPS0(_inst.FS); - //float fTemp = (float)value; - //Memory::Write_U32(*(u32*)&fTemp, Helper_Get_EA(_inst)); Memory::Write_U32(ConvertToSingle(riPS0(_inst.FS)), Helper_Get_EA(_inst)); }