mantissa_util: Implement ResidualErrorOnRightShift

Accurately calculate residual error that is shifted out
This commit is contained in:
MerryMage 2018-06-29 18:52:48 +01:00
parent 52ed365158
commit 8087e8df05
4 changed files with 113 additions and 0 deletions

View file

@ -18,6 +18,7 @@ add_library(dynarmic
common/crc32.h
common/fp/fpsr.h
common/fp/info.h
common/fp/mantissa_util.h
common/fp/process_exception.cpp
common/fp/process_exception.h
common/fp/rounding_mode.h

View file

@ -0,0 +1,48 @@
/* 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 "common/bit_util.h"
#include "common/common_types.h"
namespace Dynarmic::FP {
enum class ResidualError {
Zero,
LessThanHalf,
Half,
GreaterThanHalf,
};
template<typename MantissaT>
ResidualError ResidualErrorOnRightShift(MantissaT mantissa, int shift_amount) {
if (shift_amount <= 0 || mantissa == 0) {
return ResidualError::Zero;
}
if (shift_amount > static_cast<int>(Common::BitSize<MantissaT>())) {
return Common::MostSignificantBit(mantissa) ? ResidualError::GreaterThanHalf : ResidualError::LessThanHalf;
}
const size_t half_bit_position = static_cast<size_t>(shift_amount - 1);
const MantissaT half = static_cast<MantissaT>(1) << half_bit_position;
const MantissaT error_mask = Common::Ones<MantissaT>(static_cast<size_t>(shift_amount));
const MantissaT error = mantissa & error_mask;
if (error == 0) {
return ResidualError::Zero;
}
if (error < half) {
return ResidualError::LessThanHalf;
}
if (error == half) {
return ResidualError::Half;
}
return ResidualError::GreaterThanHalf;
}
} // namespace Dynarmic::FP