diff --git a/int_to_float.h b/int_to_float.h new file mode 100644 index 0000000..bfd870a --- /dev/null +++ b/int_to_float.h @@ -0,0 +1,118 @@ +#ifndef INT_TO_FLOAT_H +#define INT_TO_FLOAT_H + +/* Taken from here: */ +/* https://android.googlesource.com/toolchain/gcc/+/master/gcc-4.9/libgcc/config/m68k/fpgnulib.c */ + +/* the following deal with IEEE single-precision numbers */ +#define EXCESS 126L +#define SIGNBIT 0x80000000L +#define HIDDEN (1L << 23L) +#define SIGN(fp) ((fp) & SIGNBIT) +#define EXP(fp) (((fp) >> 23L) & 0xFF) +#define MANT(fp) (((fp) & 0x7FFFFFL) | HIDDEN) +#define PACK(s,e,m) ((s) | ((e) << 23L) | (m)) +/* the following deal with IEEE double-precision numbers */ +#define EXCESSD 1022L +#define HIDDEND (1L << 20L) +#define EXPDBITS 11 +#define EXPDMASK 0x7FFL +#define EXPD(fp) (((fp.l.upper) >> 20L) & 0x7FFL) +#define SIGND(fp) ((fp.l.upper) & SIGNBIT) +#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \ + (fp.l.lower >> 22)) +#define MANTDMASK 0xFFFFFL /* mask of upper part */ + +union double_long +{ + double d; + struct { + long upper; + unsigned long lower; + } l; +}; + +/* convert unsigned int to double */ +double +__floatunsidf (unsigned long a1) +{ + long exp = 32 + EXCESSD; + union double_long dl; + if (!a1) + { + dl.l.upper = dl.l.lower = 0; + return dl.d; + } + while (a1 < 0x2000000L) + { + a1 <<= 4; + exp -= 4; + } + while (a1 < 0x80000000L) + { + a1 <<= 1; + exp--; + } + /* pack up and go home */ + dl.l.upper = exp << 20L; + dl.l.upper |= (a1 >> 11L) & ~HIDDEND; + dl.l.lower = a1 << 21L; + return dl.d; +} +/* convert int to double */ +double +__floatsidf (long a1) +{ + long sign = 0, exp = 31 + EXCESSD; + union double_long dl; + if (!a1) + { + dl.l.upper = dl.l.lower = 0; + return dl.d; + } + if (a1 < 0) + { + sign = SIGNBIT; + a1 = (long)-(unsigned long)a1; + if (a1 < 0) + { + dl.l.upper = SIGNBIT | ((32 + EXCESSD) << 20L); + dl.l.lower = 0; + return dl.d; + } + } + while (a1 < 0x1000000L) + { + a1 <<= 4; + exp -= 4; + } + while (a1 < 0x40000000L) + { + a1 <<= 1; + exp--; + } + /* pack up and go home */ + dl.l.upper = sign; + dl.l.upper |= exp << 20L; + dl.l.upper |= (a1 >> 10L) & ~HIDDEND; + dl.l.lower = a1 << 22L; + return dl.d; +} + +/* convert unsigned int to float */ +float +__floatunsisf (unsigned long l) +{ + double foo = __floatunsidf (l); + return foo; +} + +/* convert int to float */ +float +__floatsisf (long l) +{ + double foo = __floatsidf (l); + return foo; +} + +#endif /* INT_TO_FLOAT_H */