Implement std::bit_cast<>

Partial implementation of std::bit_cast from C++20.
Also fix most strict-aliasing rule break warnings (gcc).
This commit is contained in:
Nekotekina 2019-06-02 00:12:17 +03:00
parent 790962425c
commit dfd50d0185
24 changed files with 145 additions and 176 deletions

View file

@ -1000,8 +1000,8 @@ bool spu_interpreter_fast::FM(spu_thread& spu, spu_opcode_t op)
//check for extended
const auto nan_check = _mm_cmpeq_ps(_mm_and_ps(primary_result, all_exp_bits), all_exp_bits);
const auto sign_mask = _mm_xor_ps(_mm_and_ps((__m128&)sign_bits, spu.gpr[op.ra].vf), _mm_and_ps((__m128&)sign_bits, spu.gpr[op.rb].vf));
const auto extended_result = _mm_or_ps(sign_mask, _mm_andnot_ps((__m128&)sign_bits, primary_result));
const auto sign_mask = _mm_xor_ps(_mm_and_ps(sign_bits, spu.gpr[op.ra].vf), _mm_and_ps(sign_bits, spu.gpr[op.rb].vf));
const auto extended_result = _mm_or_ps(sign_mask, _mm_andnot_ps(sign_bits, primary_result));
const auto final_extended = _mm_andnot_ps(denorm_operand_mask, extended_result);
//if nan, result = ext, else result = flushed
@ -1769,7 +1769,7 @@ bool spu_interpreter::MPYA(spu_thread& spu, spu_opcode_t op)
bool spu_interpreter_fast::FNMS(spu_thread& spu, spu_opcode_t op)
{
const u32 test_bits = 0x7f800000;
auto mask = _mm_set1_ps((f32&)test_bits);
auto mask = _mm_set1_ps(std::bit_cast<f32>(test_bits));
auto test_a = _mm_and_ps(spu.gpr[op.ra].vf, mask);
auto mask_a = _mm_cmpneq_ps(test_a, mask);
@ -1786,7 +1786,7 @@ bool spu_interpreter_fast::FNMS(spu_thread& spu, spu_opcode_t op)
bool spu_interpreter_fast::FMA(spu_thread& spu, spu_opcode_t op)
{
const u32 test_bits = 0x7f800000;
auto mask = _mm_set1_ps((f32&)test_bits);
auto mask = _mm_set1_ps(std::bit_cast<f32>(test_bits));
auto test_a = _mm_and_ps(spu.gpr[op.ra].vf, mask);
auto mask_a = _mm_cmpneq_ps(test_a, mask);
@ -1803,7 +1803,7 @@ bool spu_interpreter_fast::FMA(spu_thread& spu, spu_opcode_t op)
bool spu_interpreter_fast::FMS(spu_thread& spu, spu_opcode_t op)
{
const u32 test_bits = 0x7f800000;
auto mask = _mm_set1_ps((f32&)test_bits);
auto mask = _mm_set1_ps(std::bit_cast<f32>(test_bits));
auto test_a = _mm_and_ps(spu.gpr[op.ra].vf, mask);
auto mask_a = _mm_cmpneq_ps(test_a, mask);
@ -1838,20 +1838,20 @@ static void SetHostRoundingMode(u32 rn)
// Floating-point utility constants and functions
static const u32 FLOAT_MAX_NORMAL_I = 0x7F7FFFFF;
static const float& FLOAT_MAX_NORMAL = (float&)FLOAT_MAX_NORMAL_I;
static const f32 FLOAT_MAX_NORMAL = std::bit_cast<f32>(FLOAT_MAX_NORMAL_I);
static const u32 FLOAT_NAN_I = 0x7FC00000;
static const float& FLOAT_NAN = (float&)FLOAT_NAN_I;
static const f32 FLOAT_NAN = std::bit_cast<f32>(FLOAT_NAN_I);
static const u64 DOUBLE_NAN_I = 0x7FF8000000000000ULL;
static const double DOUBLE_NAN = (double&)DOUBLE_NAN_I;
static const f64 DOUBLE_NAN = std::bit_cast<f64>(DOUBLE_NAN_I);
inline bool issnan(double x)
{
return std::isnan(x) && ((s64&)x) << 12 > 0;
return std::isnan(x) && (std::bit_cast<s64>(x)) << 12 > 0;
}
inline bool issnan(float x)
{
return std::isnan(x) && ((s32&)x) << 9 > 0;
return std::isnan(x) && (std::bit_cast<s32>(x)) << 9 > 0;
}
inline bool isextended(float x)
@ -1862,14 +1862,14 @@ inline bool isextended(float x)
inline float extended(bool sign, u32 mantissa) // returns -1^sign * 2^127 * (1.mantissa)
{
u32 bits = sign << 31 | 0x7F800000 | mantissa;
return (float&)bits;
return std::bit_cast<f32>(bits);
}
inline float ldexpf_extended(float x, int exp) // ldexpf() for extended values, assumes result is in range
{
u32 bits = (u32&)x;
u32 bits = std::bit_cast<u32>(x);
if (bits << 1 != 0) bits += exp * 0x00800000;
return (float&)bits;
return std::bit_cast<f32>(bits);
}
inline bool isdenormal(float x)
@ -1979,8 +1979,8 @@ static void FA_FS(spu_thread& spu, spu_opcode_t op, bool sub)
{
if (std::signbit(a) != std::signbit(b))
{
const u32 bits = (u32&)a - 1;
result = (float&)bits;
const u32 bits = std::bit_cast<u32>(a) - 1;
result = std::bit_cast<f32>(bits);
}
else
@ -1990,8 +1990,8 @@ static void FA_FS(spu_thread& spu, spu_opcode_t op, bool sub)
{
if (std::signbit(a) != std::signbit(b))
{
const u32 bits = (u32&)b - 1;
result = (float&)bits;
const u32 bits = std::bit_cast<u32>(b) - 1;
result = std::bit_cast<f32>(bits);
}
else
result = b;
@ -2521,8 +2521,8 @@ static void FMA(spu_thread& spu, spu_opcode_t op, bool neg, bool sub)
result = new_a * new_b;
if (c != 0.0f && std::signbit(c) != sign)
{
u32 bits = (u32&)result - 1;
result = (float&)bits;
u32 bits = std::bit_cast<u32>(result) - 1;
result = std::bit_cast<f32>(bits);
}
}
else
@ -2552,8 +2552,8 @@ static void FMA(spu_thread& spu, spu_opcode_t op, bool neg, bool sub)
result = c;
if (sign != std::signbit(c))
{
u32 bits = (u32&)result - 1;
result = (float&)bits;
u32 bits = std::bit_cast<u32>(result) - 1;
result = std::bit_cast<f32>(bits);
}
}
else