/* * Interactive disassembler (IDA) * Copyright (c) 1990-2020 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 */ //------------------------------------------------------------------- /// Number of 16 bit words in ::eNE #define IEEE_NE 6 /// Number of 16 bit words in ::eNI #define IEEE_NI (IEEE_NE+3) //========================================================================== /// Array offset to exponent #define IEEE_E 1 /// Array offset to high guard word #define IEEE_M 2 /// The exponent of 1.0 #define IEEE_EXONE (0x3fff) //=================================================================== /// External x type format typedef uint16 eNE[IEEE_NE]; /// Internal format: /// - 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]; /// Exponent in eNE for NaN and Inf #define E_SPECIAL_EXP 0x7fff /// 0.0 extern const eNE ieee_ezero; #define EZERO { 0, 0000000,0000000,0000000,0000000,0000000 } /// 1.0 extern const eNE ieee_eone; #define EONE { 0, 0000000,0000000,0000000,0100000,0x3fff } /// 2.0 extern const eNE ieee_etwo; /// 32.0 extern const eNE ieee_e32; /// 6.93147180559945309417232121458176568075500134360255E-1 extern const eNE ieee_elog2; /// 1.41421356237309504880168872420969807856967187537695E0 extern const eNE ieee_esqrt2; /// 2/sqrt(PI) = 1.12837916709551257389615890312154517168810125865800E0 extern const eNE ieee_eoneopi; /// 3.14159265358979323846264338327950288419716939937511E0 extern const eNE ieee_epi; /// 5.7721566490153286060651209008240243104215933593992E-1 extern const eNE ieee_eeul; /// Clear (zero-out) the given value inline void ecleaz(eNI x) { memset(x, 0, sizeof(eNI)); } /// Move eNI => eNE idaman THREAD_SAFE void ida_export emovo(const eNI a, eNE b); /// Move eNE => eNI idaman THREAD_SAFE void ida_export emovi(const eNE a, eNI b); /// Shift NI format up (+) or down idaman THREAD_SAFE int ida_export eshift(eNI x, int sc); /// 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 THREAD_SAFE int ida_export emdnorm(eNI s, int lost, int subflg, int32 exp, int rndbase); /// \defgroup REAL_ERROR_ Floating point/IEEE Conversion codes /// Return values for and processor_t::realcvt_t request //@{ #define REAL_ERROR_FORMAT -1 ///< not supported format for current .idp #define REAL_ERROR_RANGE -2 ///< number too big (small) for store (mem NOT modified) #define REAL_ERROR_BADDATA -3 ///< illegal real data for load (IEEE data not filled) //@} // /// \name Prototypes /// IDP module event prototype -- should be implemented in idp //@{ /// Floating point conversion function: implemented by \ph{realcvt}. /// \param m pointer to data /// \param e 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) /// \retval 0 ok /// \retval \ref REAL_ERROR_ on error int idaapi realcvt(void *m, eNE e, uint16 swt); /// Little endian int l_realcvt(void *m, eNE e, uint16 swt); /// Big endian int b_realcvt(void *m, eNE e, uint16 swt); //@} /// Standard IEEE 754 floating point conversion function. /// See comment for realcvt(). idaman THREAD_SAFE int ida_export ieee_realcvt(void *m, eNE e, uint16 swt); /// \name Misc arithmetic/conversion functions /// \retval 0 ok /// \retval 1 overfloat / underfloat /// \retval 2 illegal data (asctoreal()) /// \retval 3 divide by 0 (ediv()) /// \retval 4 too big for integer (eetol()) //@{ /// IEEE to ascii string. /// \param mode broken down into: /// - low byte: number of digits after '.' /// - second byte: FPNUM_LENGTH /// - third byte: FPNUM_DIGITS idaman THREAD_SAFE void ida_export realtoasc(char *buf, size_t bufsize, const eNE x, uint mode); /// ascii string to IEEE idaman THREAD_SAFE int ida_export asctoreal(const char **sss, eNE y); /// long to IEEE idaman THREAD_SAFE void ida_export eltoe(sval_t l, eNE e); /// int64 to IEEE idaman THREAD_SAFE void ida_export eltoe64(int64 l, eNE e); /// uint64 to IEEE idaman THREAD_SAFE void ida_export eltoe64u(uint64 l, eNE e); /// IEEE to long (+-0.5 if flg) idaman THREAD_SAFE int ida_export eetol(sval_t *l, const eNE a, bool roundflg); /// IEEE to long (+-0.5 if flg) idaman THREAD_SAFE int ida_export eetol64(int64 *l, const eNE a, bool roundflg); /// IEEE to ulong (+-0.5 if flg) idaman THREAD_SAFE int ida_export eetol64u(uint64 *l, const eNE a, bool roundflg); /// b = a*(2**pwr2) idaman THREAD_SAFE int ida_export eldexp(const eNE a, int32 pwr2, eNE b); /// if(!subflg) c = a + b, /// else c = a - b idaman THREAD_SAFE int ida_export eadd(const eNE a, const eNE b, eNE c, int subflg); /// c = a * b idaman THREAD_SAFE int ida_export emul(const eNE a, const eNE b, eNE c); /// c = a / b idaman THREAD_SAFE int ida_export ediv(const eNE a, const eNE b, eNE c); // predefined functions /// \cond void eclear(eNE a); void emov(eNE a, eNE b); void eabs(eNE x); int esign(eNE x); /// \endcond /// x = 0 #define eclear(a) memset(a, 0, sizeof(eNE)) /// b = a #define emov(a, b) memcpy(b, a, sizeof(eNE)) /// x = |x| #define eabs(x) (x[IEEE_NE-1] &= 0x7fff) #ifdef __cplusplus /// x = -x inline void eneg(eNE x) { if ( x[IEEE_NE-1] != 0 ) x[IEEE_NE-1] ^= 0x8000; } #endif /// x < 0 ? /// \note non standard answer is returned #define esign(x) (x[IEEE_NE-1] & 0x8000) //@} /// Comparison. /// \retval 0 if a = b /// \retval 1 if a > b /// \retval -1 if a < b idaman THREAD_SAFE int ida_export ecmp(const eNE a, const eNE b); /// Check 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, MAXEXP_DOUBLE = 0x400, MAXEXP_LNGDBL = 0x4000; //@} /// See ::fpvalue_kind_t idaman THREAD_SAFE fpvalue_kind_t ida_export get_fpvalue_kind(const eNE a, uint16 reserved = 0); #endif