From 557a01a787005c35e1cae40f5063ca95e21185c2 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 24 May 2019 18:55:31 -0400 Subject: [PATCH] common/fp/op: Add soft-float implementation of FPCompareEQ This will be used to implement the half-precision floating-point variants of FCMEQ in following changes. --- src/CMakeLists.txt | 2 ++ src/common/fp/op.h | 1 + src/common/fp/op/FPCompare.cpp | 41 ++++++++++++++++++++++++++++++++++ src/common/fp/op/FPCompare.h | 17 ++++++++++++++ 4 files changed, 61 insertions(+) create mode 100644 src/common/fp/op/FPCompare.cpp create mode 100644 src/common/fp/op/FPCompare.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5e7cc5a7..0e3827ad 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,6 +24,8 @@ add_library(dynarmic common/fp/info.h common/fp/mantissa_util.h common/fp/op.h + common/fp/op/FPCompare.cpp + common/fp/op/FPCompare.h common/fp/op/FPConvert.cpp common/fp/op/FPConvert.h common/fp/op/FPMulAdd.cpp diff --git a/src/common/fp/op.h b/src/common/fp/op.h index b8ee1441..b1bd0ee0 100644 --- a/src/common/fp/op.h +++ b/src/common/fp/op.h @@ -6,6 +6,7 @@ #pragma once +#include "common/fp/op/FPCompare.h" #include "common/fp/op/FPConvert.h" #include "common/fp/op/FPMulAdd.h" #include "common/fp/op/FPRecipEstimate.h" diff --git a/src/common/fp/op/FPCompare.cpp b/src/common/fp/op/FPCompare.cpp new file mode 100644 index 00000000..7e16dd60 --- /dev/null +++ b/src/common/fp/op/FPCompare.cpp @@ -0,0 +1,41 @@ +/* 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. + */ + +#include "common/fp/fpcr.h" +#include "common/fp/fpsr.h" +#include "common/fp/op/FPCompare.h" +#include "common/fp/process_exception.h" +#include "common/fp/unpacked.h" + +namespace Dynarmic::FP { + +template +bool FPCompareEQ(FPT lhs, FPT rhs, FPCR fpcr, FPSR& fpsr) { + const auto unpacked1 = FPUnpack(lhs, fpcr, fpsr); + const auto unpacked2 = FPUnpack(rhs, fpcr, fpsr); + const auto type1 = std::get(unpacked1); + const auto type2 = std::get(unpacked2); + const auto& value1 = std::get(unpacked1); + const auto& value2 = std::get(unpacked2); + + if (type1 == FPType::QNaN || type1 == FPType::SNaN || + type2 == FPType::QNaN || type2 == FPType::SNaN) { + if (type1 == FPType::SNaN || type2 == FPType::SNaN) { + FPProcessException(FPExc::InvalidOp, fpcr, fpsr); + } + + // Comparisons against NaN are never equal. + return false; + } + + return value1 == value2 || (type1 == FPType::Zero && type2 == FPType::Zero); +} + +template bool FPCompareEQ(u16 lhs, u16 rhs, FPCR fpcr, FPSR& fpsr); +template bool FPCompareEQ(u32 lhs, u32 rhs, FPCR fpcr, FPSR& fpsr); +template bool FPCompareEQ(u64 lhs, u64 rhs, FPCR fpcr, FPSR& fpsr); + +} // namespace Dynarmic::FP diff --git a/src/common/fp/op/FPCompare.h b/src/common/fp/op/FPCompare.h new file mode 100644 index 00000000..33802848 --- /dev/null +++ b/src/common/fp/op/FPCompare.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 +bool FPCompareEQ(FPT lhs, FPT rhs, FPCR fpcr, FPSR& fpsr); + +} // namespace Dynarmic::FP