/* 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/assert.h" #include "common/bit_util.h" #include "common/fp/fpcr.h" #include "common/fp/fpsr.h" #include "common/fp/info.h" #include "common/fp/process_exception.h" #include "common/fp/process_nan.h" #include "common/fp/unpacked.h" namespace Dynarmic::FP { template FPT FPProcessNaN(FPType type, FPT op, FPCR fpcr, FPSR& fpsr) { ASSERT(type == FPType::QNaN || type == FPType::SNaN); constexpr size_t topfrac = FPInfo::explicit_mantissa_width - 1; FPT result = op; if (type == FPType::SNaN) { result = Common::ModifyBit(op, true); FPProcessException(FPExc::InvalidOp, fpcr, fpsr); } if (fpcr.DN()) { result = FPInfo::DefaultNaN(); } return result; } template u16 FPProcessNaN(FPType type, u16 op, FPCR fpcr, FPSR& fpsr); template u32 FPProcessNaN(FPType type, u32 op, FPCR fpcr, FPSR& fpsr); template u64 FPProcessNaN(FPType type, u64 op, FPCR fpcr, FPSR& fpsr); template std::optional FPProcessNaNs(FPType type1, FPType type2, FPT op1, FPT op2, FPCR fpcr, FPSR& fpsr) { if (type1 == FPType::SNaN) { return FPProcessNaN(type1, op1, fpcr, fpsr); } if (type2 == FPType::SNaN) { return FPProcessNaN(type2, op2, fpcr, fpsr); } if (type1 == FPType::QNaN) { return FPProcessNaN(type1, op1, fpcr, fpsr); } if (type2 == FPType::QNaN) { return FPProcessNaN(type2, op2, fpcr, fpsr); } return std::nullopt; } template std::optional FPProcessNaNs(FPType type1, FPType type2, u16 op1, u16 op2, FPCR fpcr, FPSR& fpsr); template std::optional FPProcessNaNs(FPType type1, FPType type2, u32 op1, u32 op2, FPCR fpcr, FPSR& fpsr); template std::optional FPProcessNaNs(FPType type1, FPType type2, u64 op1, u64 op2, FPCR fpcr, FPSR& fpsr); template std::optional FPProcessNaNs3(FPType type1, FPType type2, FPType type3, FPT op1, FPT op2, FPT op3, FPCR fpcr, FPSR& fpsr) { if (type1 == FPType::SNaN) { return FPProcessNaN(type1, op1, fpcr, fpsr); } if (type2 == FPType::SNaN) { return FPProcessNaN(type2, op2, fpcr, fpsr); } if (type3 == FPType::SNaN) { return FPProcessNaN(type3, op3, fpcr, fpsr); } if (type1 == FPType::QNaN) { return FPProcessNaN(type1, op1, fpcr, fpsr); } if (type2 == FPType::QNaN) { return FPProcessNaN(type2, op2, fpcr, fpsr); } if (type3 == FPType::QNaN) { return FPProcessNaN(type3, op3, fpcr, fpsr); } return std::nullopt; } template std::optional FPProcessNaNs3(FPType type1, FPType type2, FPType type3, u16 op1, u16 op2, u16 op3, FPCR fpcr, FPSR& fpsr); template std::optional FPProcessNaNs3(FPType type1, FPType type2, FPType type3, u32 op1, u32 op2, u32 op3, FPCR fpcr, FPSR& fpsr); template std::optional FPProcessNaNs3(FPType type1, FPType type2, FPType type3, u64 op1, u64 op2, u64 op3, FPCR fpcr, FPSR& fpsr); } // namespace Dynarmic::FP