fp/info: Replace constant value generators with FPValue

Instead of having multiple different functions we can just have one.
This commit is contained in:
MerryMage 2018-07-26 10:59:33 +01:00
parent da261772ea
commit 8f75a1fe04
3 changed files with 25 additions and 6 deletions

View file

@ -6,6 +6,7 @@
#pragma once #pragma once
#include "common/bit_util.h"
#include "common/common_types.h" #include "common/common_types.h"
namespace Dynarmic::FP { namespace Dynarmic::FP {
@ -33,8 +34,6 @@ struct FPInfo<u32> {
static constexpr u32 Infinity(bool sign) { return exponent_mask | Zero(sign); } static constexpr u32 Infinity(bool sign) { return exponent_mask | Zero(sign); }
static constexpr u32 MaxNormal(bool sign) { return (exponent_mask - 1) | Zero(sign); } static constexpr u32 MaxNormal(bool sign) { return (exponent_mask - 1) | Zero(sign); }
static constexpr u32 DefaultNaN() { return exponent_mask | (u32(1) << (explicit_mantissa_width - 1)); } static constexpr u32 DefaultNaN() { return exponent_mask | (u32(1) << (explicit_mantissa_width - 1)); }
static constexpr u32 OnePointFive(bool sign) { return Zero(sign) | (u32(1) << (explicit_mantissa_width - 1)) | (u32(exponent_bias) << explicit_mantissa_width); }
static constexpr u32 Two(bool sign) { return Zero(sign) | (u32(exponent_bias + 1) << explicit_mantissa_width); }
}; };
template<> template<>
@ -57,8 +56,26 @@ struct FPInfo<u64> {
static constexpr u64 Infinity(bool sign) { return exponent_mask | Zero(sign); } static constexpr u64 Infinity(bool sign) { return exponent_mask | Zero(sign); }
static constexpr u64 MaxNormal(bool sign) { return (exponent_mask - 1) | Zero(sign); } static constexpr u64 MaxNormal(bool sign) { return (exponent_mask - 1) | Zero(sign); }
static constexpr u64 DefaultNaN() { return exponent_mask | (u64(1) << (explicit_mantissa_width - 1)); } static constexpr u64 DefaultNaN() { return exponent_mask | (u64(1) << (explicit_mantissa_width - 1)); }
static constexpr u64 OnePointFive(bool sign) { return Zero(sign) | (u64(1) << (explicit_mantissa_width - 1)) | (u64(exponent_bias) << explicit_mantissa_width); }
static constexpr u64 Two(bool sign) { return Zero(sign) | (u64(exponent_bias + 1) << explicit_mantissa_width); }
}; };
/// value = (sign ? -1 : +1) * 2^exponent * value
/// @note We do not handle denormals. Denormals will static_assert.
template<typename FPT, bool sign, int exponent, FPT value>
constexpr FPT FPValue() {
if constexpr (value == 0) {
return FPInfo<FPT>::Zero(sign);
}
constexpr int point_position = static_cast<int>(FPInfo<FPT>::mantissa_width);
constexpr int highest_bit = Common::HighestSetBit(value);
constexpr int offset = point_position - highest_bit;
constexpr int normalized_exponent = exponent - offset + point_position;
static_assert(offset >= 0);
static_assert(normalized_exponent >= FPInfo<FPT>::exponent_min && normalized_exponent <= FPInfo<FPT>::exponent_max);
constexpr FPT mantissa = (value << offset) & FPInfo<FPT>::mantissa_mask;
constexpr FPT biased_exponent = static_cast<FPT>(normalized_exponent + FPInfo<FPT>::exponent_bias);
return FPInfo<FPT>::Zero(sign) | mantissa | (biased_exponent << FPInfo<FPT>::explicit_mantissa_width);
}
} // namespace Dynarmic::FP } // namespace Dynarmic::FP

View file

@ -33,7 +33,8 @@ FPT FPRSqrtStepFused(FPT op1, FPT op2, FPCR fpcr, FPSR& fpsr) {
const bool zero2 = type2 == FPType::Zero; const bool zero2 = type2 == FPType::Zero;
if ((inf1 && zero2) || (zero1 && inf2)) { if ((inf1 && zero2) || (zero1 && inf2)) {
return FPInfo<FPT>::OnePointFive(false); // return +1.5
return FPValue<FPT, false, -1, 3>();
} }
if (inf1 || inf2) { if (inf1 || inf2) {

View file

@ -33,7 +33,8 @@ FPT FPRecipStepFused(FPT op1, FPT op2, FPCR fpcr, FPSR& fpsr) {
const bool zero2 = type2 == FPType::Zero; const bool zero2 = type2 == FPType::Zero;
if ((inf1 && zero2) || (zero1 && inf2)) { if ((inf1 && zero2) || (zero1 && inf2)) {
return FPInfo<FPT>::Two(false); // return +2.0
return FPValue<FPT, false, 0, 2>();
} }
if (inf1 || inf2) { if (inf1 || inf2) {