From b168c2a9f9a67027dc311c8b30e4647f95b16df0 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 2 Mar 2019 17:53:50 -0500 Subject: [PATCH] common/fp/op: Add operations for floating-point reciprocal exponents --- src/CMakeLists.txt | 2 + src/common/fp/op.h | 1 + src/common/fp/op/FPRecipExponent.cpp | 70 ++++++++++++++++++++++++++++ src/common/fp/op/FPRecipExponent.h | 17 +++++++ 4 files changed, 90 insertions(+) create mode 100644 src/common/fp/op/FPRecipExponent.cpp create mode 100644 src/common/fp/op/FPRecipExponent.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c6a51f87..cfb45452 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,6 +28,8 @@ add_library(dynarmic common/fp/op/FPMulAdd.h common/fp/op/FPRecipEstimate.cpp common/fp/op/FPRecipEstimate.h + common/fp/op/FPRecipExponent.cpp + common/fp/op/FPRecipExponent.h common/fp/op/FPRecipStepFused.cpp common/fp/op/FPRecipStepFused.h common/fp/op/FPRoundInt.cpp diff --git a/src/common/fp/op.h b/src/common/fp/op.h index f7232407..c792e50e 100644 --- a/src/common/fp/op.h +++ b/src/common/fp/op.h @@ -8,6 +8,7 @@ #include "common/fp/op/FPMulAdd.h" #include "common/fp/op/FPRecipEstimate.h" +#include "common/fp/op/FPRecipExponent.h" #include "common/fp/op/FPRecipStepFused.h" #include "common/fp/op/FPRoundInt.h" #include "common/fp/op/FPRSqrtEstimate.h" diff --git a/src/common/fp/op/FPRecipExponent.cpp b/src/common/fp/op/FPRecipExponent.cpp new file mode 100644 index 00000000..eaa7addb --- /dev/null +++ b/src/common/fp/op/FPRecipExponent.cpp @@ -0,0 +1,70 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2018 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#include + +#include "common/common_types.h" +#include "common/bit_util.h" +#include "common/fp/fpcr.h" +#include "common/fp/fpsr.h" +#include "common/fp/info.h" +#include "common/fp/op/FPRecipExponent.h" +#include "common/fp/process_nan.h" +#include "common/fp/unpacked.h" + +namespace Dynarmic::FP { +namespace { +// We don't care about unreachable code warnings here +// TODO: Remove this warning disabling of warnings when +// half-float support is added. +#ifdef _MSC_VER +#pragma warning(disable:4702) +#endif +template +FPT DetermineExponentValue(size_t value) { + if constexpr (sizeof(FPT) == sizeof(u32)) { + return static_cast(Common::Bits<23, 30>(value)); + } + + if constexpr (sizeof(FPT) == sizeof(u64)) { + return static_cast(Common::Bits<52, 62>(value)); + } + + // Half-float + return static_cast(Common::Bits<10, 14>(value)); +} +#ifdef _MSC_VER +#pragma warning(default:4702) +#endif +} // Anonymous namespace + +template +FPT FPRecipExponent(FPT op, FPCR fpcr, FPSR& fpsr) { + const auto [type, sign, value] = FPUnpack(op, fpcr, fpsr); + (void)value; + + if (type == FPType::SNaN || type == FPType::QNaN) { + return FPProcessNaN(type, op, fpcr, fpsr); + } + + const FPT sign_bits = FPInfo::Zero(sign); + const FPT exponent = DetermineExponentValue(op); + + // Zero and denormals + if (exponent == 0) { + const FPT max_exponent = Common::Ones(FPInfo::exponent_width) - 1; + return FPT(sign_bits | (max_exponent << FPInfo::explicit_mantissa_width)); + } + + // Infinities and normals + const auto negated_exponent = (~exponent << FPInfo::explicit_mantissa_width) & FPInfo::exponent_mask; + return FPT(sign_bits | negated_exponent); +} + +template u32 FPRecipExponent(u32 op, FPCR fpcr, FPSR& fpsr); +template u64 FPRecipExponent(u64 op, FPCR fpcr, FPSR& fpsr); + +} // namespace Dynarmic::FP diff --git a/src/common/fp/op/FPRecipExponent.h b/src/common/fp/op/FPRecipExponent.h new file mode 100644 index 00000000..285d0e9d --- /dev/null +++ b/src/common/fp/op/FPRecipExponent.h @@ -0,0 +1,17 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2019 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#pragma once + +namespace Dynarmic::FP { + +class FPCR; +class FPSR; + +template +FPT FPRecipExponent(FPT op, FPCR fpcr, FPSR& fpsr); + +} // namespace Dynarmic::FP