mirror of
https://git.suyu.dev/suyu/dynarmic.git
synced 2026-01-06 14:38:17 +01:00
This function is defined as always disabling the AHP bit in the fpcr before performing any operations. At the same time, rename the original FPUnpack function to FPUnpackBase to match the pseudocode in the ARM reference manual.
89 lines
2.3 KiB
C++
89 lines
2.3 KiB
C++
/* 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.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <tuple>
|
|
|
|
#include "common/common_types.h"
|
|
#include "common/fp/fpcr.h"
|
|
|
|
namespace Dynarmic::FP {
|
|
|
|
class FPSR;
|
|
enum class RoundingMode;
|
|
|
|
enum class FPType {
|
|
Nonzero,
|
|
Zero,
|
|
Infinity,
|
|
QNaN,
|
|
SNaN,
|
|
};
|
|
|
|
constexpr size_t normalized_point_position = 62;
|
|
|
|
/// value = (sign ? -1 : +1) * mantissa/(2^62) * 2^exponent
|
|
/// 63rd bit of mantissa is always set (unless value is zero)
|
|
struct FPUnpacked {
|
|
bool sign;
|
|
int exponent;
|
|
u64 mantissa;
|
|
};
|
|
|
|
inline bool operator==(const FPUnpacked& a, const FPUnpacked& b) {
|
|
return std::tie(a.sign, a.exponent, a.mantissa) == std::tie(b.sign, b.exponent, b.mantissa);
|
|
}
|
|
|
|
/// return value = (sign ? -1 : +1) * value * 2^exponent
|
|
constexpr FPUnpacked ToNormalized(bool sign, int exponent, u64 value) {
|
|
if (value == 0) {
|
|
return {sign, 0, 0};
|
|
}
|
|
|
|
const int highest_bit = Common::HighestSetBit(value);
|
|
const int offset = static_cast<int>(normalized_point_position) - highest_bit;
|
|
value <<= offset;
|
|
exponent -= offset - normalized_point_position;
|
|
return {sign, exponent, value};
|
|
}
|
|
|
|
template<typename FPT>
|
|
std::tuple<FPType, bool, FPUnpacked> FPUnpackBase(FPT op, FPCR fpcr, FPSR& fpsr);
|
|
|
|
template<typename FPT>
|
|
std::tuple<FPType, bool, FPUnpacked> FPUnpack(FPT op, FPCR fpcr, FPSR& fpsr) {
|
|
fpcr.AHP(false);
|
|
return FPUnpackBase(op, fpcr, fpsr);
|
|
}
|
|
|
|
template<typename FPT>
|
|
std::tuple<FPType, bool, FPUnpacked> FPUnpackCV(FPT op, FPCR fpcr, FPSR& fpsr) {
|
|
fpcr.FZ16(false);
|
|
return FPUnpack(op, fpcr, fpsr);
|
|
}
|
|
|
|
template<typename FPT>
|
|
FPT FPRoundBase(FPUnpacked op, FPCR fpcr, RoundingMode rounding, FPSR& fpsr);
|
|
|
|
template<typename FPT>
|
|
FPT FPRound(FPUnpacked op, FPCR fpcr, RoundingMode rounding, FPSR& fpsr) {
|
|
fpcr.AHP(false);
|
|
return FPRoundBase<FPT>(op, fpcr, rounding, fpsr);
|
|
}
|
|
|
|
template<typename FPT>
|
|
FPT FPRoundCV(FPUnpacked op, FPCR fpcr, RoundingMode rounding, FPSR& fpsr) {
|
|
fpcr.FZ16(false);
|
|
return FPRoundBase<FPT>(op, fpcr, rounding, fpsr);
|
|
}
|
|
|
|
template<typename FPT>
|
|
FPT FPRound(FPUnpacked op, FPCR fpcr, FPSR& fpsr) {
|
|
return FPRound<FPT>(op, fpcr, fpcr.RMode(), fpsr);
|
|
}
|
|
|
|
} // namespace Dynarmic::FP
|