mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
673 lines
18 KiB
C++
673 lines
18 KiB
C++
/* ###
|
|
* IP: GHIDRA
|
|
* NOTE: uses some windows and sparc specific floating point definitions
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#include "float.hh"
|
|
#include "address.hh"
|
|
|
|
#include <cmath>
|
|
#include <limits>
|
|
|
|
namespace ghidra {
|
|
|
|
using std::ldexp;
|
|
using std::frexp;
|
|
using std::signbit;
|
|
using std::sqrt;
|
|
using std::floor;
|
|
using std::ceil;
|
|
using std::round;
|
|
using std::fabs;
|
|
|
|
/// Set format for a given encoding size according to IEEE 754 standards
|
|
/// \param sz is the size of the encoding in bytes
|
|
FloatFormat::FloatFormat(int4 sz)
|
|
|
|
{
|
|
size = sz;
|
|
|
|
if (size == 4) {
|
|
signbit_pos = 31;
|
|
exp_pos = 23;
|
|
exp_size = 8;
|
|
frac_pos = 0;
|
|
frac_size = 23;
|
|
bias = 127;
|
|
jbitimplied = true;
|
|
}
|
|
else if (size == 8) {
|
|
signbit_pos = 63;
|
|
exp_pos = 52;
|
|
exp_size = 11;
|
|
frac_pos = 0;
|
|
frac_size = 52;
|
|
bias = 1023;
|
|
jbitimplied = true;
|
|
}
|
|
maxexponent = (1<<exp_size)-1;
|
|
calcPrecision();
|
|
}
|
|
|
|
/// \param sign is set to \b true if the value should be negative
|
|
/// \param signif is the fractional part
|
|
/// \param exp is the exponent
|
|
/// \return the constructed floating-point value
|
|
double FloatFormat::createFloat(bool sign,uintb signif,int4 exp)
|
|
|
|
{
|
|
signif >>= 1; // Throw away 1 bit of precision we will
|
|
// lose anyway, to make sure highbit is 0
|
|
int4 precis = 8*sizeof(uintb) - 1; // fullword - 1 we threw away
|
|
double res = (double)signif;
|
|
int4 expchange = exp - precis + 1; // change in exponent is precis
|
|
// -1 integer bit
|
|
res = ldexp(res,expchange);
|
|
if (sign)
|
|
res = res * -1.0;
|
|
return res;
|
|
}
|
|
|
|
/// \brief Extract the sign, fractional, and exponent from a given floating-point value
|
|
///
|
|
/// \param x is the given value
|
|
/// \param sgn passes back the sign
|
|
/// \param signif passes back the fractional part
|
|
/// \param exp passes back the exponent
|
|
/// \return the floating-point class of the value
|
|
FloatFormat::floatclass FloatFormat::extractExpSig(double x,bool *sgn,uintb *signif,int4 *exp)
|
|
|
|
{
|
|
int4 e;
|
|
|
|
*sgn = signbit(x);
|
|
if (x == 0.0) return zero;
|
|
if (std::isinf(x)) return infinity;
|
|
if (std::isnan(x)) return nan;
|
|
if (*sgn)
|
|
x = -x;
|
|
double norm = frexp(x,&e); // norm is between 1/2 and 1
|
|
norm = ldexp(norm,8*sizeof(uintb)-1); // norm between 2^62 and 2^63
|
|
|
|
*signif = (uintb)norm; // Convert to normalized integer
|
|
*signif <<= 1;
|
|
|
|
e -= 1; // Consider normalization between 1 and 2
|
|
*exp = e;
|
|
return normalized;
|
|
}
|
|
|
|
/// \param x is an encoded floating-point value
|
|
/// \return the fraction part of the value aligned to the top of the word
|
|
uintb FloatFormat::extractFractionalCode(uintb x) const
|
|
|
|
{
|
|
x >>= frac_pos; // Eliminate bits below
|
|
x <<= 8*sizeof(uintb) - frac_size; // Align with top of word
|
|
return x;
|
|
}
|
|
|
|
/// \param x is an encoded floating-point value
|
|
/// \return the sign bit
|
|
bool FloatFormat::extractSign(uintb x) const
|
|
|
|
{
|
|
x >>= signbit_pos;
|
|
return ((x&1)!=0);
|
|
}
|
|
|
|
/// \param x is an encoded floating-point value
|
|
/// \return the (signed) exponent
|
|
int4 FloatFormat::extractExponentCode(uintb x) const
|
|
|
|
{
|
|
x >>= exp_pos;
|
|
uintb mask = 1;
|
|
mask = (mask<<exp_size) - 1;
|
|
return (int4)(x & mask);
|
|
}
|
|
|
|
/// \param x is an encoded value (with fraction part set to zero)
|
|
/// \param code is the new fractional value to set
|
|
/// \return the encoded value with the fractional filled in
|
|
uintb FloatFormat::setFractionalCode(uintb x,uintb code) const
|
|
|
|
{
|
|
// Align with bottom of word, also drops bits of precision
|
|
// we don't have room for
|
|
code >>= 8*sizeof(uintb) - frac_size;
|
|
code <<= frac_pos; // Move bits into position;
|
|
x |= code;
|
|
return x;
|
|
}
|
|
|
|
/// \param x is an encoded value (with sign set to zero)
|
|
/// \param sign is the sign bit to set
|
|
/// \return the encoded value with the sign bit set
|
|
uintb FloatFormat::setSign(uintb x,bool sign) const
|
|
|
|
{
|
|
if (!sign) return x; // Assume bit is already zero
|
|
uintb mask = 1;
|
|
mask <<= signbit_pos;
|
|
x |= mask; // Stick in the bit
|
|
return x;
|
|
}
|
|
|
|
/// \param x is an encoded value (with exponent set to zero)
|
|
/// \param code is the exponent to set
|
|
/// \return the encoded value with the new exponent
|
|
uintb FloatFormat::setExponentCode(uintb x,uintb code) const
|
|
|
|
{
|
|
code <<= exp_pos; // Move bits into position
|
|
x |= code;
|
|
return x;
|
|
}
|
|
|
|
/// \param sgn is set to \b true for negative zero, \b false for positive
|
|
/// \return the encoded zero
|
|
uintb FloatFormat::getZeroEncoding(bool sgn) const
|
|
|
|
{
|
|
uintb res = 0;
|
|
// Use IEEE 754 standard for zero encoding
|
|
res = setFractionalCode(res,0);
|
|
res = setExponentCode(res,0);
|
|
return setSign(res,sgn);
|
|
}
|
|
|
|
/// \param sgn is set to \b true for negative infinity, \b false for positive
|
|
/// \return the encoded infinity
|
|
uintb FloatFormat::getInfinityEncoding(bool sgn) const
|
|
|
|
{
|
|
uintb res = 0;
|
|
// Use IEEE 754 standard for infinity encoding
|
|
res = setFractionalCode(res,0);
|
|
res = setExponentCode(res,(uintb)maxexponent);
|
|
return setSign(res,sgn);
|
|
}
|
|
|
|
/// \param sgn is set to \b true for negative NaN, \b false for positive
|
|
/// \return the encoded NaN
|
|
uintb FloatFormat::getNaNEncoding(bool sgn) const
|
|
|
|
{
|
|
uintb res = 0;
|
|
// Use IEEE 754 standard for NaN encoding
|
|
uintb mask = 1;
|
|
mask <<= 8*sizeof(uintb)-1; // Create "quiet" NaN
|
|
res = setFractionalCode(res,mask);
|
|
res = setExponentCode(res,(uintb)maxexponent);
|
|
return setSign(res,sgn);
|
|
}
|
|
|
|
void FloatFormat::calcPrecision(void)
|
|
|
|
{
|
|
decimalMinPrecision = (int4)floor(frac_size * 0.30103);
|
|
// Precision needed to guarantee IEEE 754 binary -> decimal -> binary round trip conversion
|
|
decimalMaxPrecision = (int4)ceil((frac_size + 1) * 0.30103) + 1;
|
|
}
|
|
|
|
/// \param encoding is the encoding value
|
|
/// \param type points to the floating-point class, which is passed back
|
|
/// \return the equivalent double value
|
|
double FloatFormat::getHostFloat(uintb encoding,floatclass *type) const
|
|
|
|
{
|
|
bool sgn = extractSign(encoding);
|
|
uintb frac = extractFractionalCode(encoding);
|
|
int4 exp = extractExponentCode(encoding);
|
|
bool normal = true;
|
|
|
|
if (exp == 0) {
|
|
if ( frac == 0 ) { // Floating point zero
|
|
*type = zero;
|
|
return sgn ? -0.0 : +0.0;
|
|
}
|
|
*type = denormalized;
|
|
// Number is denormalized
|
|
normal = false;
|
|
}
|
|
else if (exp == maxexponent) {
|
|
if ( frac == 0 ) { // Floating point infinity
|
|
*type = infinity;
|
|
double infinity = std::numeric_limits<double>::infinity();
|
|
return sgn ? -infinity : +infinity;
|
|
}
|
|
*type = nan;
|
|
// encoding is "Not a Number" NaN
|
|
double nan = std::numeric_limits<double>::quiet_NaN();
|
|
return sgn ? -nan : +nan; // Sign is usually ignored
|
|
}
|
|
else
|
|
*type = normalized;
|
|
|
|
// Get "true" exponent and fractional
|
|
exp -= bias;
|
|
if (normal && jbitimplied) {
|
|
frac >>= 1; // Make room for 1 jbit
|
|
uintb highbit = 1;
|
|
highbit <<= 8*sizeof(uintb)-1;
|
|
frac |= highbit; // Stick bit in at top
|
|
}
|
|
return createFloat(sgn,frac,exp);
|
|
}
|
|
|
|
/// \brief Round a floating point value to the nearest even
|
|
///
|
|
/// \param signif the significant bits of a floating point value
|
|
/// \param lowbitpos the position in signif of the floating point
|
|
/// \return true if we rounded up
|
|
|
|
bool FloatFormat::roundToNearestEven(uintb &signif, int4 lowbitpos)
|
|
|
|
{
|
|
uintb lowbitmask = (lowbitpos < 8 * sizeof(uintb)) ? ((uintb)1 << lowbitpos) : 0;
|
|
uintb midbitmask = (uintb)1 << (lowbitpos - 1);
|
|
uintb epsmask = midbitmask - 1;
|
|
bool odd = (signif & lowbitmask) != 0;
|
|
if ((signif & midbitmask) != 0 && ((signif & epsmask) != 0 || odd)) {
|
|
signif += midbitmask;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/// \param host is the double value to convert
|
|
/// \return the equivalent encoded value
|
|
uintb FloatFormat::getEncoding(double host) const
|
|
|
|
{
|
|
floatclass type;
|
|
bool sgn;
|
|
uintb signif;
|
|
int4 exp;
|
|
|
|
type = extractExpSig(host, &sgn, &signif, &exp);
|
|
if (type == zero)
|
|
return getZeroEncoding(sgn);
|
|
else if (type == infinity)
|
|
return getInfinityEncoding(sgn);
|
|
else if (type == nan)
|
|
return getNaNEncoding(sgn);
|
|
|
|
// convert exponent and fractional to their encodings
|
|
exp += bias;
|
|
|
|
if (exp < -frac_size) // Exponent is too small to represent
|
|
return getZeroEncoding(sgn); // TODO handle round to non-zero
|
|
|
|
if (exp < 1) { // Must be denormalized
|
|
if (roundToNearestEven(signif, 8 * sizeof(uintb) - frac_size - exp)) {
|
|
// TODO handle round to normal case
|
|
if ((signif >> (8 * sizeof(uintb) - 1)) == 0) {
|
|
signif = (uintb)1 << (8 * sizeof(uintb) - 1);
|
|
exp += 1;
|
|
}
|
|
}
|
|
uintb res = getZeroEncoding(sgn);
|
|
return setFractionalCode(res, signif >> (-exp));
|
|
}
|
|
|
|
if (roundToNearestEven(signif, 8 * sizeof(uintb) - frac_size - 1)) {
|
|
// if high bit is clear, then the add overflowed. Increase exp and set
|
|
// signif to 1.
|
|
if ((signif >> (8 * sizeof(uintb) - 1)) == 0) {
|
|
signif = (uintb)1 << (8 * sizeof(uintb) - 1);
|
|
exp += 1;
|
|
}
|
|
}
|
|
|
|
if (exp >= maxexponent) // Exponent is too big to represent
|
|
return getInfinityEncoding(sgn);
|
|
|
|
if (jbitimplied && (exp != 0))
|
|
signif <<= 1; // Cut off top bit (which should be 1)
|
|
|
|
uintb res = 0;
|
|
res = setFractionalCode(res, signif);
|
|
res = setExponentCode(res, (uintb)exp);
|
|
return setSign(res, sgn);
|
|
}
|
|
|
|
|
|
/// \param encoding is the value in the \e other FloatFormat
|
|
/// \param formin is the \e other FloatFormat
|
|
/// \return the equivalent value in \b this FloatFormat
|
|
uintb FloatFormat::convertEncoding(uintb encoding,
|
|
const FloatFormat *formin) const
|
|
|
|
{
|
|
bool sgn = formin->extractSign(encoding);
|
|
uintb signif = formin->extractFractionalCode(encoding);
|
|
int4 exp = formin->extractExponentCode(encoding);
|
|
|
|
if (exp == formin->maxexponent) { // NaN or INFINITY encoding
|
|
exp = maxexponent;
|
|
if (signif != 0)
|
|
return getNaNEncoding(sgn);
|
|
else
|
|
return getInfinityEncoding(sgn);
|
|
}
|
|
|
|
if (exp == 0) { // incoming is subnormal
|
|
if (signif == 0)
|
|
return getZeroEncoding(sgn);
|
|
|
|
// normalize
|
|
int4 lz = count_leading_zeros(signif);
|
|
signif <<= lz;
|
|
exp = -formin->bias - lz;
|
|
}
|
|
else { // incoming is normal
|
|
exp -= formin->bias;
|
|
if (jbitimplied)
|
|
signif = ((uintb)1 << (8 * sizeof(uintb) - 1)) | (signif >> 1);
|
|
}
|
|
|
|
exp += bias;
|
|
|
|
if (exp < -frac_size) // Exponent is too small to represent
|
|
return getZeroEncoding(sgn); // TODO handle round to non-zero
|
|
|
|
if (exp < 1) { // Must be denormalized
|
|
if (roundToNearestEven(signif, 8 * sizeof(uintb) - frac_size - exp)) {
|
|
// TODO handle carry to normal case
|
|
if ((signif >> (8 * sizeof(uintb) - 1)) == 0) {
|
|
signif = (uintb)1 << (8 * sizeof(uintb) - 1);
|
|
exp += 1;
|
|
}
|
|
}
|
|
uintb res = getZeroEncoding(sgn);
|
|
return setFractionalCode(res, signif >> (-exp));
|
|
}
|
|
|
|
if (roundToNearestEven(signif, 8 * sizeof(uintb) - frac_size - 1)) {
|
|
// if high bit is clear, then the add overflowed. Increase exp and set
|
|
// signif to 1.
|
|
if ((signif >> (8 * sizeof(uintb) - 1)) == 0) {
|
|
signif = (uintb)1 << (8 * sizeof(uintb) - 1);
|
|
exp += 1;
|
|
}
|
|
}
|
|
|
|
if (exp >= maxexponent) // Exponent is too big to represent
|
|
return getInfinityEncoding(sgn);
|
|
|
|
if (jbitimplied && (exp != 0))
|
|
signif <<= 1; // Cut off top bit (which should be 1)
|
|
|
|
uintb res = 0;
|
|
res = setFractionalCode(res, signif);
|
|
res = setExponentCode(res, (uintb)exp);
|
|
return setSign(res, sgn);
|
|
}
|
|
|
|
/// The string should be printed with the minimum number of digits to uniquely specify the underlying
|
|
/// binary value. This currently only works for the 32-bit and 64-bit IEEE 754 formats.
|
|
/// If the \b forcesci parameter is \b true, the string will always be printed using scientific notation.
|
|
/// \param host is the given value already converted to the host's \b double format.
|
|
/// \param forcesci is \b true if the value should be printed in scientific notation.
|
|
/// \return the decimal representation as a string
|
|
string FloatFormat::printDecimal(double host,bool forcesci) const
|
|
|
|
{
|
|
string res;
|
|
for(int4 prec=decimalMinPrecision;;++prec) {
|
|
ostringstream s;
|
|
if (forcesci) {
|
|
s.setf( ios::scientific ); // Set to scientific notation
|
|
s.precision(prec-1); // scientific doesn't include first digit in precision count
|
|
}
|
|
else {
|
|
s.unsetf( ios::floatfield ); // Use "default" notation to allow fewer digits to be printed if possible
|
|
s.precision(prec);
|
|
}
|
|
s << host;
|
|
if (prec == decimalMaxPrecision) {
|
|
return s.str();
|
|
}
|
|
res = s.str();
|
|
double roundtrip = 0.0;
|
|
istringstream t(res);
|
|
if (size <= 4) {
|
|
float tmp = 0.0;
|
|
t >> tmp;
|
|
roundtrip = tmp;
|
|
}
|
|
else {
|
|
t >> roundtrip;
|
|
}
|
|
if (roundtrip == host)
|
|
break;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
// Currently we emulate floating point operations on the target
|
|
// By converting the encoding to the host's encoding and then
|
|
// performing the operation using the host's floating point unit
|
|
// then the host's encoding is converted back to the targets encoding
|
|
|
|
/// \param a is the first floating-point value
|
|
/// \param b is the second floating-point value
|
|
/// \return \b true if (a == b)
|
|
uintb FloatFormat::opEqual(uintb a,uintb b) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val1 = getHostFloat(a,&type);
|
|
double val2 = getHostFloat(b,&type);
|
|
uintb res = (val1 == val2) ? 1 : 0;
|
|
return res;
|
|
}
|
|
|
|
/// \param a is the first floating-point value
|
|
/// \param b is the second floating-point value
|
|
/// \return \b true if (a != b)
|
|
uintb FloatFormat::opNotEqual(uintb a,uintb b) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val1 = getHostFloat(a,&type);
|
|
double val2 = getHostFloat(b,&type);
|
|
uintb res = (val1 != val2) ? 1 : 0;
|
|
return res;
|
|
}
|
|
|
|
/// \param a is the first floating-point value
|
|
/// \param b is the second floating-point value
|
|
/// \return \b true if (a < b)
|
|
uintb FloatFormat::opLess(uintb a,uintb b) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val1 = getHostFloat(a,&type);
|
|
double val2 = getHostFloat(b,&type);
|
|
uintb res = (val1 < val2) ? 1 : 0;
|
|
return res;
|
|
}
|
|
|
|
/// \param a is the first floating-point value
|
|
/// \param b is the second floating-point value
|
|
/// \return \b true if (a <= b)
|
|
uintb FloatFormat::opLessEqual(uintb a,uintb b) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val1 = getHostFloat(a,&type);
|
|
double val2 = getHostFloat(b,&type);
|
|
uintb res = (val1 <= val2) ? 1 : 0;
|
|
return res;
|
|
}
|
|
|
|
/// \param a is an encoded floating-point value
|
|
/// \return \b true if a is Not-a-Number
|
|
uintb FloatFormat::opNan(uintb a) const
|
|
|
|
{
|
|
floatclass type;
|
|
getHostFloat(a,&type);
|
|
uintb res = (type == FloatFormat::nan) ? 1 : 0;
|
|
return res;
|
|
}
|
|
|
|
/// \param a is the first floating-point value
|
|
/// \param b is the second floating-point value
|
|
/// \return a + b
|
|
uintb FloatFormat::opAdd(uintb a,uintb b) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val1 = getHostFloat(a,&type);
|
|
double val2 = getHostFloat(b,&type);
|
|
return getEncoding(val1 + val2);
|
|
}
|
|
|
|
/// \param a is the first floating-point value
|
|
/// \param b is the second floating-point value
|
|
/// \return a / b
|
|
uintb FloatFormat::opDiv(uintb a,uintb b) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val1 = getHostFloat(a,&type);
|
|
double val2 = getHostFloat(b,&type);
|
|
return getEncoding(val1 / val2);
|
|
}
|
|
|
|
/// \param a is the first floating-point value
|
|
/// \param b is the second floating-point value
|
|
/// \return a * b
|
|
uintb FloatFormat::opMult(uintb a,uintb b) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val1 = getHostFloat(a,&type);
|
|
double val2 = getHostFloat(b,&type);
|
|
return getEncoding(val1 * val2);
|
|
}
|
|
|
|
/// \param a is the first floating-point value
|
|
/// \param b is the second floating-point value
|
|
/// \return a - b
|
|
uintb FloatFormat::opSub(uintb a,uintb b) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val1 = getHostFloat(a,&type);
|
|
double val2 = getHostFloat(b,&type);
|
|
return getEncoding(val1 - val2);
|
|
}
|
|
|
|
/// \param a is an encoded floating-point value
|
|
/// \return -a
|
|
uintb FloatFormat::opNeg(uintb a) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val = getHostFloat(a,&type);
|
|
return getEncoding(-val);
|
|
}
|
|
|
|
/// \param a is an encoded floating-point value
|
|
/// \return abs(a)
|
|
uintb FloatFormat::opAbs(uintb a) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val = getHostFloat(a,&type);
|
|
return getEncoding(fabs(val));
|
|
}
|
|
|
|
/// \param a is an encoded floating-point value
|
|
/// \return sqrt(a)
|
|
uintb FloatFormat::opSqrt(uintb a) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val = getHostFloat(a,&type);
|
|
return getEncoding(sqrt(val));
|
|
}
|
|
|
|
/// \param a is a signed integer value
|
|
/// \param sizein is the number of bytes in the integer encoding
|
|
/// \return a converted to an encoded floating-point value
|
|
uintb FloatFormat::opInt2Float(uintb a,int4 sizein) const
|
|
|
|
{
|
|
intb ival = sign_extend(a,8*sizein-1);
|
|
double val = (double) ival; // Convert integer to float
|
|
return getEncoding(val);
|
|
}
|
|
|
|
/// \param a is an encoded floating-point value
|
|
/// \param outformat is the desired output FloatFormat
|
|
/// \return a converted to the output FloatFormat
|
|
uintb FloatFormat::opFloat2Float(uintb a,const FloatFormat &outformat) const
|
|
|
|
{
|
|
return outformat.convertEncoding(a, this);
|
|
}
|
|
|
|
/// \param a is an encoded floating-point value
|
|
/// \param sizeout is the desired encoding size of the output
|
|
/// \return an integer encoding of a
|
|
uintb FloatFormat::opTrunc(uintb a,int4 sizeout) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val = getHostFloat(a,&type);
|
|
intb ival = (intb) val; // Convert to integer
|
|
uintb res = (uintb) ival; // Convert to unsigned
|
|
res &= calc_mask(sizeout); // Truncate to proper size
|
|
return res;
|
|
}
|
|
|
|
/// \param a is an encoded floating-point value
|
|
/// \return ceil(a)
|
|
uintb FloatFormat::opCeil(uintb a) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val = getHostFloat(a,&type);
|
|
return getEncoding(ceil(val));
|
|
}
|
|
|
|
/// \param a is an encoded floating-point value
|
|
/// \return floor(a)
|
|
uintb FloatFormat::opFloor(uintb a) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val = getHostFloat(a,&type);
|
|
return getEncoding(floor(val));
|
|
}
|
|
|
|
/// \param a is an encoded floating-point value
|
|
/// \return round(a)
|
|
uintb FloatFormat::opRound(uintb a) const
|
|
|
|
{
|
|
floatclass type;
|
|
double val = getHostFloat(a,&type);
|
|
// return getEncoding(floor(val+.5)); // round half up
|
|
return getEncoding(round(val)); // round half away from zero
|
|
}
|
|
|
|
} // End namespace ghidra
|