Repository URL to install this package:
Version:
9.0~241217-2.fc42 ▾
|
/*
* Interactive disassembler (IDA)
* Copyright (c) 1990-2024 Hex-Rays
* ALL RIGHTS RESERVED.
* Floating Point Number Libary.
* Copyright (c) 1995-2006 by Iouri Kharon.
* E-mail: yjh@styx.cabel.net
*
*/
#ifndef _IEEE_H_
#define _IEEE_H_
/*! \file ieee.h
\brief IEEE floating point functions
*/
struct fpvalue_t; // processor-independent representation of floats
#define FPVAL_NWORDS 8 ///< number of words in fpvalue_t
/// Floating value kinds.
/// They are useful when checking for NaN/Inf
enum fpvalue_kind_t
{
FPV_BADARG, ///< wrong value of max_exp
FPV_NORM, ///< regular value
FPV_NAN, ///< NaN
FPV_PINF, ///< positive infinity
FPV_NINF, ///< negative infinity
};
/// \name max_exp values
/// Common values for max_exp (for IEEE floating point values)
///@{
const uint32
MAXEXP_FLOAT = 0x80, ///< maximum exponent for 32-bit float
MAXEXP_DOUBLE = 0x400, ///< maximum exponent for 64-bit double
MAXEXP_LNGDBL = 0x4000; ///< maximum exponent for 80-bit long double
///@}
/// \defgroup REAL_ERROR_ Floating point/IEEE Conversion codes
/// Return values for ieee_realcvt and processor_t::realcvt request
enum fpvalue_error_t
{
REAL_ERROR_OK = 1, ///< no error
REAL_ERROR_FORMAT = -1, ///< realcvt: not supported format for current .idp
REAL_ERROR_RANGE = -2, ///< realcvt: number too big (small) for store (mem NOT modified)
REAL_ERROR_BADDATA = -3, ///< realcvt: illegal real data for load (IEEE data not filled)
REAL_ERROR_FPOVER = 2, ///< floating overflow or underflow
REAL_ERROR_BADSTR = 3, ///< asctoreal: illegal input string
REAL_ERROR_ZERODIV = 4, ///< ediv: divide by 0
REAL_ERROR_INTOVER = 5, ///< eetol*: integer overflow
};
/// Standard IEEE 754 floating point conversion function
/// \param m pointer to data
/// \param out internal IEEE format data
/// \param swt operation:
/// - 000: load trunc. float (DEC ^F) 2 bytes (m->e)
/// - 001: load float 4 bytes (m->e)
/// - 003: load double 8 bytes (m->e)
/// - 004: load long double 10 bytes (m->e)
/// - 005: load long double 12 bytes (m->e)
/// - 010: store trunc. float (DEC ^F) 2 bytes (e->m)
/// - 011: store float 4 bytes (e->m)
/// - 013: store double 8 bytes (e->m)
/// - 014: store long double 10 bytes (e->m)
/// - 015: store long double 12 bytes (e->m)
/// bit 0x80 forces little endian even for big endian processors
/// \return fpvalue_error_t
idaman THREAD_SAFE fpvalue_error_t ida_export ieee_realcvt(void *m, fpvalue_t *out, uint16 swt);
// Helper functions. Better use members of fpvalue_t, they are nicer.
idaman THREAD_SAFE void ida_export realtoasc(char *buf, size_t bufsize, const fpvalue_t &x, uint mode);
idaman THREAD_SAFE fpvalue_error_t ida_export asctoreal(const char **sss, fpvalue_t *out);
idaman THREAD_SAFE void ida_export eltoe(sval_t l, fpvalue_t *vout);
idaman THREAD_SAFE void ida_export eltoe64(int64 l, fpvalue_t *vout);
idaman THREAD_SAFE void ida_export eltoe64u(uint64 l, fpvalue_t *vout);
idaman THREAD_SAFE fpvalue_error_t ida_export eetol(sval_t *out, const fpvalue_t &a, bool roundflg);
idaman THREAD_SAFE fpvalue_error_t ida_export eetol64(int64 *out, const fpvalue_t &a, bool roundflg);
idaman THREAD_SAFE fpvalue_error_t ida_export eetol64u(uint64 *out, const fpvalue_t &a, bool roundflg);
idaman THREAD_SAFE fpvalue_error_t ida_export eldexp(const fpvalue_t &a, int32 pwr2, fpvalue_t *zout);
idaman THREAD_SAFE fpvalue_error_t ida_export eadd(const fpvalue_t &a, const fpvalue_t &b, fpvalue_t *zout, bool subflg);
idaman THREAD_SAFE fpvalue_error_t ida_export emul(const fpvalue_t &a, const fpvalue_t &b, fpvalue_t *zout);
idaman THREAD_SAFE fpvalue_error_t ida_export ediv(const fpvalue_t &a, const fpvalue_t &b, fpvalue_t *zout);
idaman THREAD_SAFE int ida_export ecmp(const fpvalue_t &a, const fpvalue_t &b);
idaman THREAD_SAFE fpvalue_kind_t ida_export get_fpvalue_kind(const fpvalue_t &a, uint16 reserved = 0);
//------------------------------------------------------------------------
/// Processor-independent representation of a floating point value.
/// IDA uses this structure to store and manipulate floating point values.
struct fpvalue_t
{
uint16 w[FPVAL_NWORDS];
void clear(void) { memset(this, 0, sizeof(*this)); }
DECLARE_COMPARISONS(fpvalue_t) { return ecmp(*this, r); }
/// Convert to the processor-independent representation.
fpvalue_error_t from_half(uint16 fpval) { return ieee_realcvt(&fpval, this, sizeof(fpval)/2-1); }
fpvalue_error_t from_float(float fpval) { return ieee_realcvt(&fpval, this, sizeof(fpval)/2-1); }
fpvalue_error_t from_double(double fpval) { return ieee_realcvt(&fpval, this, sizeof(fpval)/2-1); }
/// Convert from the processor-independent representation.
fpvalue_error_t to_half(uint16 *fpval) const { return ieee_realcvt(fpval, (fpvalue_t*)this, 8|(sizeof(*fpval)/2-1)); }
fpvalue_error_t to_float(float *fpval) const { return ieee_realcvt(fpval, (fpvalue_t*)this, 8|(sizeof(*fpval)/2-1)); }
fpvalue_error_t to_double(double *fpval) const { return ieee_realcvt(fpval, (fpvalue_t*)this, 8|(sizeof(*fpval)/2-1)); }
/// Conversions for 10-byte floating point values.
fpvalue_error_t from_10bytes(const void *fpval) { return ieee_realcvt((void *)fpval, this, 4); }
fpvalue_error_t to_10bytes(void *fpval) const { return ieee_realcvt(fpval, (fpvalue_t*)this, 8|4); }
/// Conversions for 12-byte floating point values.
fpvalue_error_t from_12bytes(const void *fpval) { return ieee_realcvt((void*)fpval, this, 5); }
fpvalue_error_t to_12bytes(void *fpval) const { return ieee_realcvt(fpval, (fpvalue_t*)this, 8|5); }
/// Convert string to IEEE.
/// \param p_str pointer to pointer to string. it will advanced.
fpvalue_error_t from_str(const char **p_str) { return asctoreal(p_str, this); }
/// Convert IEEE to string.
/// \param buf the output buffer
/// \param bufsize the size of the output buffer
/// \param mode broken down into:
/// - low byte: number of digits after '.'
/// - second byte: FPNUM_LENGTH
/// - third byte: FPNUM_DIGITS
void to_str(char *buf, size_t bufsize, uint mode) const { realtoasc(buf, bufsize, *this, mode); }
/// Convert integer to IEEE
void from_sval(sval_t x) { eltoe(x, this); }
void from_int64(int64 x) { eltoe64(x, this); }
void from_uint64(uint64 x) { eltoe64u(x, this); }
/// Convert IEEE to integer (+-0.5 if round)
fpvalue_error_t to_sval(sval_t *out, bool round=false) const { return eetol(out, *this, round); }
fpvalue_error_t to_int64(int64 *out, bool round=false) const { return eetol64(out, *this, round); }
fpvalue_error_t to_uint64(uint64 *out, bool round=false) const { return eetol64u(out, *this, round); }
/// Arithmetic operations
fpvalue_error_t fadd(const fpvalue_t &y) { return eadd(*this, y, this, false); }
fpvalue_error_t fsub(const fpvalue_t &y) { return eadd(*this, y, this, true); }
fpvalue_error_t fmul(const fpvalue_t &y) { return emul(*this, y, this); }
fpvalue_error_t fdiv(const fpvalue_t &y) { return ediv(*this, y, this); }
/// Multiply by a power of 2.
fpvalue_error_t mul_pow2(int32 power_of_2) { return eldexp(*this, power_of_2, this); }
/// Calculate absolute value.
void eabs() { w[FPVAL_NWORDS-1] &= 0x7fff; }
/// Is negative value?
bool is_negative() const { return (w[FPVAL_NWORDS-1] & 0x8000) != 0; }
/// Negate.
void negate()
{
if ( w[FPVAL_NWORDS-1] != 0 )
w[FPVAL_NWORDS-1] ^= 0x8000;
}
/// Get value kind.
fpvalue_kind_t get_kind() const { return get_fpvalue_kind(*this, 0); }
};
//------------------------------------------------------------------------
/// The exponent of 1.0
#define IEEE_EXONE (0x3FFF)
/// Exponent in fpvalue_t for NaN and Inf
#define E_SPECIAL_EXP 0x7FFF
#if !defined(NO_OBSOLETE_FUNCS) || defined(IEEE_SOURCE)
#define IEEE_NI (FPVAL_NWORDS+3) ///< Number of 16 bit words in ::eNI
#define IEEE_E 1 ///< Array offset to exponent
#define IEEE_M 2 ///< Array offset to high guard word
/// There is one more internal format used by IDA to store intermediate values.
/// - 0 : sign (0/1)
/// - 1 : exponent (based of #IEEE_EXONE). If exp = 0, value = 0.
/// - 2 : high word of mantissa (always zero after normalize)
typedef uint16 eNI[IEEE_NI];
#ifdef IEEE_SOURCE
# define IEEE_DEPRECATED
#else
# define IEEE_DEPRECATED DEPRECATED
#endif
inline IEEE_DEPRECATED void ecleaz(eNI x)
{
if ( x != nullptr )
memset(x, 0, sizeof(eNI));
}
idaman IEEE_DEPRECATED THREAD_SAFE void ida_export emovo(const eNI a, fpvalue_t *vout); /// Move eNI => eNE
idaman IEEE_DEPRECATED THREAD_SAFE void ida_export emovi(const fpvalue_t &a, eNI vout); /// Move eNE => eNI
idaman IEEE_DEPRECATED THREAD_SAFE int ida_export eshift(eNI x, int sc); /// Shift NI format up (+) or down
/// Normalize and round off.
/// \param s the internal format number to be rounded
/// \param lost indicates whether or not the number is exact.
/// this is the so-called sticky bit.
/// \param subflg indicates whether the number was obtained
/// by a subtraction operation. In that case if lost is nonzero
/// then the number is slightly smaller than indicated.
/// \param exp the biased exponent, which may be negative.
/// the exponent field of "s" is ignored but is replaced by
/// "exp" as adjusted by normalization and rounding.
/// \param rndbase if 0 => is the rounding control.
/// else is processor defined base (rndprc)
/// \return success
idaman IEEE_DEPRECATED THREAD_SAFE bool ida_export emdnorm(eNI s, bool lost, bool subflg, int32 exp, int rndbase);
#endif
#endif