From 7a3158a693dc657c722f055d68725711b8a55d92 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 11 Apr 2018 18:51:59 -0400 Subject: [PATCH] Interpreter_FPUtils: Don't use a union to type-pun between integral and FP types The previous code invokes undefined behavior. memcpy will optimize away to the relevant loads and stores while maintaining well-defined behavior. --- .../PowerPC/Interpreter/Interpreter_FPUtils.h | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index d2adcd7b6f..8ddd9a7d72 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include "Common/CPUDetect.h" @@ -71,16 +72,28 @@ inline double ForceDouble(double d) inline double Force25Bit(double d) { - MathUtil::IntDouble x(d); - x.i = (x.i & 0xFFFFFFFFF8000000ULL) + (x.i & 0x8000000); - return x.d; + u64 integral; + std::memcpy(&integral, &d, sizeof(u64)); + + integral = (integral & 0xFFFFFFFFF8000000ULL) + (integral & 0x8000000); + + double result; + std::memcpy(&result, &integral, sizeof(double)); + + return result; } inline double MakeQuiet(double d) { - MathUtil::IntDouble x(d); - x.i |= MathUtil::DOUBLE_QBIT; - return x.d; + u64 integral; + std::memcpy(&integral, &d, sizeof(u64)); + + integral |= MathUtil::DOUBLE_QBIT; + + double result; + std::memcpy(&result, &integral, sizeof(double)); + + return result; } // these functions allow globally modify operations behaviour