common/fp/op/FPConvert: Add half-precision instantiations to FPConvert

This commit is contained in:
Lioncash 2019-03-23 09:58:02 -04:00 committed by MerryMage
parent f01afc5ae6
commit c57b146fb2

View file

@ -17,25 +17,17 @@
namespace Dynarmic::FP { namespace Dynarmic::FP {
namespace { namespace {
// We don't care about unreachable code warnings here
// TODO: Remove this disabling of warnings when
// half-float support is added.
#ifdef _MSC_VER
#pragma warning(disable:4702)
#endif
template <typename FPT_TO, typename FPT_FROM> template <typename FPT_TO, typename FPT_FROM>
FPT_TO FPConvertNaN(FPT_FROM op) { FPT_TO FPConvertNaN(FPT_FROM op) {
const bool sign = Common::Bit<Common::BitSize<FPT_FROM>() - 1>(op); const bool sign = Common::Bit<Common::BitSize<FPT_FROM>() - 1>(op);
const u64 frac = [op] { const u64 frac = [op] {
if constexpr (sizeof(FPT_FROM) == sizeof(u64)) { if constexpr (sizeof(FPT_FROM) == sizeof(u64)) {
return Common::Bits<0, 50>(op); return Common::Bits<0, 50>(op);
} } else if constexpr (sizeof(FPT_FROM) == sizeof(u32)) {
if constexpr (sizeof(FPT_FROM) == sizeof(u32)) {
return u64{Common::Bits<0, 21>(op)} << 29; return u64{Common::Bits<0, 21>(op)} << 29;
} } else {
return u64{Common::Bits<0, 8>(op)} << 42; return u64{Common::Bits<0, 8>(op)} << 42;
}
}(); }();
const size_t dest_bit_size = Common::BitSize<FPT_TO>(); const size_t dest_bit_size = Common::BitSize<FPT_TO>();
@ -44,17 +36,12 @@ FPT_TO FPConvertNaN(FPT_FROM op) {
if constexpr (sizeof(FPT_TO) == sizeof(u64)) { if constexpr (sizeof(FPT_TO) == sizeof(u64)) {
return FPT_TO(shifted_sign | exponent << 52 | frac); return FPT_TO(shifted_sign | exponent << 52 | frac);
} } else if constexpr (sizeof(FPT_TO) == sizeof(u32)) {
if constexpr (sizeof(FPT_TO) == sizeof(u32)) {
return FPT_TO(shifted_sign | exponent << 22 | Common::Bits<29, 50>(frac)); return FPT_TO(shifted_sign | exponent << 22 | Common::Bits<29, 50>(frac));
} } else {
return FPT_TO(shifted_sign | exponent << 9 | Common::Bits<42, 50>(frac)); return FPT_TO(shifted_sign | exponent << 9 | Common::Bits<42, 50>(frac));
}
} }
#ifdef _MSC_VER
#pragma warning(default:4702)
#endif
} // Anonymous namespace } // Anonymous namespace
template <typename FPT_TO, typename FPT_FROM> template <typename FPT_TO, typename FPT_FROM>
@ -63,7 +50,7 @@ FPT_TO FPConvert(FPT_FROM op, FPCR fpcr, RoundingMode rounding_mode, FPSR& fpsr)
const bool is_althp = Common::BitSize<FPT_TO>() == 16 && fpcr.AHP(); const bool is_althp = Common::BitSize<FPT_TO>() == 16 && fpcr.AHP();
if (type == FPType::SNaN || type == FPType::QNaN) { if (type == FPType::SNaN || type == FPType::QNaN) {
FPT_TO result{}; std::uintmax_t result{};
if (is_althp) { if (is_althp) {
result = FPInfo<FPT_TO>::Zero(sign); result = FPInfo<FPT_TO>::Zero(sign);
@ -77,26 +64,30 @@ FPT_TO FPConvert(FPT_FROM op, FPCR fpcr, RoundingMode rounding_mode, FPSR& fpsr)
FPProcessException(FPExc::InvalidOp, fpcr, fpsr); FPProcessException(FPExc::InvalidOp, fpcr, fpsr);
} }
return result; return FPT_TO(result);
} }
if (type == FPType::Infinity) { if (type == FPType::Infinity) {
if (is_althp) { if (is_althp) {
FPProcessException(FPExc::InvalidOp, fpcr, fpsr); FPProcessException(FPExc::InvalidOp, fpcr, fpsr);
return static_cast<FPT_TO>(u32{sign} << 15 | 0b111111111111111); return FPT_TO(u32{sign} << 15 | 0b111111111111111);
} }
return FPInfo<FPT_TO>::Infinity(sign); return FPT_TO(FPInfo<FPT_TO>::Infinity(sign));
} }
if (type == FPType::Zero) { if (type == FPType::Zero) {
return FPInfo<FPT_TO>::Zero(sign); return FPT_TO(FPInfo<FPT_TO>::Zero(sign));
} }
return FPRoundCV<FPT_TO>(value, fpcr, rounding_mode, fpsr); return FPRoundCV<FPT_TO>(value, fpcr, rounding_mode, fpsr);
} }
template u64 FPConvert<u64, u32>(u32 op, FPCR fpcr, RoundingMode rounding_mode, FPSR& fpsr); template u16 FPConvert<u16, u32>(u32 op, FPCR fpcr, RoundingMode rounding_mode, FPSR& fpsr);
template u16 FPConvert<u16, u64>(u64 op, FPCR fpcr, RoundingMode rounding_mode, FPSR& fpsr);
template u32 FPConvert<u32, u16>(u16 op, FPCR fpcr, RoundingMode rounding_mode, FPSR& fpsr);
template u32 FPConvert<u32, u64>(u64 op, FPCR fpcr, RoundingMode rounding_mode, FPSR& fpsr); template u32 FPConvert<u32, u64>(u64 op, FPCR fpcr, RoundingMode rounding_mode, FPSR& fpsr);
template u64 FPConvert<u64, u16>(u16 op, FPCR fpcr, RoundingMode rounding_mode, FPSR& fpsr);
template u64 FPConvert<u64, u32>(u32 op, FPCR fpcr, RoundingMode rounding_mode, FPSR& fpsr);
} // namespace Dynarmic::FP } // namespace Dynarmic::FP