119 lines
2.4 KiB
C
119 lines
2.4 KiB
C
#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 */
|