fp/info: Replace constant value generators with FPValue
Instead of having multiple different functions we can just have one.
This commit is contained in:
parent
da261772ea
commit
8f75a1fe04
3 changed files with 25 additions and 6 deletions
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue