#ifndef __SDC51_FLOAT_H
#define __SDC51_FLOAT_H 1
+
+#include <limits.h>
+
#define FLT_RADIX 2
#define FLT_MANT_DIG 24
#define FLT_EPSILON 1.192092896E-07F
#define FLT_MAX 3.402823466E+38F
#define FLT_MAX_10_EXP (+38)
+/* the following deal with IEEE single-precision numbers */
+#define EXCESS 126
+#define SIGNBIT ((unsigned long)0x80000000)
+#define HIDDEN (unsigned long)(1 << 23)
+#define SIGN(fp) ((fp >> (8*sizeof(fp)-1)) & 1)
+#define EXP(fp) (((fp) >> 23) & (unsigned int) 0x00FF)
+#define MANT(fp) (((fp) & (unsigned long)0x007FFFFF) | HIDDEN)
+#define NORM 0xff000000
+#define PACK(s,e,m) ((s) | ((e) << 23) | (m))
+
+float _uchar2fs (unsigned char);
+float _schar2fs (signed char);
+float _uint2fs (unsigned int);
+float _sint2fs (signed int);
+float _ulong2fs (unsigned long);
+float _slong2fs (signed long);
+unsigned char _fs2uchar (float);
+signed char _fs2schar (float);
+unsigned int _fs2uint (float);
+signed int _fs2sint (float);
+unsigned long _fs2ulong (float);
+signed long _fs2slong (float);
+
+float _fsadd (float, float);
+float _fssub (float, float);
+float _fsmul (float, float);
+float _fsdiv (float, float);
+
+char _fslt (float, float);
+char _fseq (float, float);
+char _fsqt (float, float);
+
#endif
-#include <limits.h>
-
-signed long __fs2slong (float f);
+#include <float.h>
/* convert float to signed char */
signed char __fs2schar (float f) {
-#include <limits.h>
-
-signed long __fs2slong (float f);
+#include <float.h>
/* convert float to signed int */
signed int __fs2sint (float f) {
-#include <limits.h>
-
-unsigned long __fs2ulong (float a1);
+#include <float.h>
/* convert float to signed long */
signed long __fs2slong (float f) {
return 0;
if (f<0) {
- if (f<=LONG_MIN)
- return LONG_MIN;
return -__fs2ulong(-f);
} else {
- if (f>=LONG_MAX)
- return LONG_MAX;
return __fs2ulong(f);
}
}
-#include <limits.h>
-
-unsigned long __fs2ulong (float a1);
+#include <float.h>
/* convert float to unsigned char */
unsigned char __fs2uchar (float f) {
-#include <limits.h>
+#include <float.h>
unsigned long __fs2ulong (float a1);
** uunet!motown!pipeline!phw
*/
-/* (c)2000: hacked a little by johan.knol@iduna.nl for sdcc */
+/* (c)2000/2001: hacked a little by johan.knol@iduna.nl for sdcc */
-#include <limits.h>
-
-/* the following deal with IEEE single-precision numbers */
-#define EXCESS 126
-#define SIGNBIT ((unsigned long)0x80000000)
-#define HIDDEN (unsigned long)(1 << 23)
-#define SIGN(fp) ((fp >> (8*sizeof(fp)-1)) & 1)
-#define EXP(fp) (((fp) >> 23) & (unsigned int) 0x00FF)
-#define MANT(fp) (((fp) & (unsigned long) 0x007FFFFF) | HIDDEN)
-#define PACK(s,e,m) ((s) | ((e) << 23) | (m))
+#include <float.h>
union float_long
{
if (!fl1.l || SIGN(fl1.l))
return (0);
- if (a1>=ULONG_MAX)
- return ULONG_MAX;
-
exp = EXP (fl1.l) - EXCESS - 24;
l = MANT (fl1.l);
-/* the following deal with IEEE single-precision numbers */
-#define EXCESS 126
-#define SIGNBIT ((unsigned long)0x80000000)
-#define HIDDEN (unsigned long)(1 << 23)
-#define SIGN(fp) ((fp >> (8*sizeof(fp)-1)) & 1)
-#define EXP(fp) (((fp) >> 23) & (unsigned int)0x00FF)
-#define MANT(fp) (((fp) & (unsigned long)0x007FFFFF) | HIDDEN)
-#define PACK(s,e,m) ((s) | ((e) << 23) | (m))
+/*
+** libgcc support for software floating point.
+** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved.
+** Permission is granted to do *anything* you want with this file,
+** commercial or otherwise, provided this message remains intact. So there!
+** I would appreciate receiving any updates/patches/changes that anyone
+** makes, and am willing to be the repository for said changes (am I
+** making a big mistake?).
+**
+** Pat Wood
+** Pipeline Associates, Inc.
+** pipeline!phw@motown.com or
+** sun!pipeline!phw or
+** uunet!motown!pipeline!phw
+*/
+
+/* (c)2000/2001: hacked a little by johan.knol@iduna.nl for sdcc */
+
+#include <float.h>
union float_long
{
float f;
- long l;
+ unsigned long l;
};
+
/* add two floats */
-float
-__fsadd (float a1, float a2)
+float __fsadd (float a1, float a2)
{
volatile long mant1, mant2;
volatile union float_long fl1, fl2;
if (exp2 > exp1 + 25)
return (fl2.f);
- /* do everything in excess precision so's we can round later */
- mant1 = MANT (fl1.l) << 6;
- mant2 = MANT (fl2.l) << 6;
+ mant1 = MANT (fl1.l);
+ mant2 = MANT (fl2.l);
if (SIGN (fl1.l))
mant1 = -mant1;
else if (!mant1)
return (0);
- /* normalize up */
- while (!((unsigned long)mant1 & (unsigned long) 0xE0000000))
- {
- mant1 <<= 1;
- exp1--;
- }
-
- /* normalize down? */
- if ((unsigned long)mant1 & (unsigned long)(1 << 30))
- {
- mant1 >>= 1 ;
- exp1++;
- }
-
- /* round to even */
- mant1 += (mant1 & (unsigned long)0x40) ? (unsigned long) 0x20 : (unsigned long) 0x1F;
-
- /* normalize down? */
- if (mant1 & (unsigned long)(1 << 30))
- {
- mant1 >>= 1;
- exp1++;
- }
-
- /* lose extra precision */
- mant1 >>= 6;
+ /* normalize */
+ /* jwk: TODO: changing the next two whiles in nested ifs
+ seriously breaks it. Why?????????????????? */
+ while (mant1<HIDDEN) {
+ mant1 <<= 1;
+ exp1--;
+ }
+
+ while (mant1 & 0xff000000) {
+ // round off
+ if (mant1&1)
+ mant1 += 2;
+ mant1 >>= 1 ;
+ exp1++;
+ }
/* turn off hidden bit */
- mant1 = (unsigned long)mant1 & ~HIDDEN;
+ mant1 &= ~HIDDEN;
/* pack up and go home */
fl1.l = PACK (sign, (unsigned long) exp1, mant1);
+
return (fl1.f);
}
** I would appreciate receiving any updates/patches/changes that anyone
** makes, and am willing to be the repository for said changes (am I
** making a big mistake?).
-
-Warning! Only single-precision is actually implemented. This file
-won't really be much use until double-precision is supported.
-
-However, once that is done, this file might eventually become a
-replacement for libgcc1.c. It might also make possible
-cross-compilation for an IEEE target machine from a non-IEEE
-host such as a VAX.
-
-If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu.
-
-
**
** Pat Wood
** Pipeline Associates, Inc.
** pipeline!phw@motown.com or
** sun!pipeline!phw or
** uunet!motown!pipeline!phw
-**
-** 05/01/91 -- V1.0 -- first release to gcc mailing lists
-** 05/04/91 -- V1.1 -- added float and double prototypes and return values
-** -- fixed problems with adding and subtracting zero
-** -- fixed rounding in truncdfsf2
-** -- fixed SWAP define and tested on 386
*/
-/*
-** The following are routines that replace the libgcc soft floating point
-** routines that are called automatically when -msoft-float is selected.
-** The support single and double precision IEEE format, with provisions
-** for byte-swapped machines (tested on 386). Some of the double-precision
-** routines work at full precision, but most of the hard ones simply punt
-** and call the single precision routines, producing a loss of accuracy.
-** long long support is not assumed or included.
-** Overall accuracy is close to IEEE (actually 68882) for single-precision
-** arithmetic. I think there may still be a 1 in 1000 chance of a bit
-** being rounded the wrong way during a multiply. I'm not fussy enough to
-** bother with it, but if anyone is, knock yourself out.
-**
-** Efficiency has only been addressed where it was obvious that something
-** would make a big difference. Anyone who wants to do this right for
-** best speed should go in and rewrite in assembler.
-**
-** I have tested this only on a 68030 workstation and 386/ix integrated
-** in with -msoft-float.
-*/
+/* (c)2000/2001: hacked a little by johan.knol@iduna.nl for sdcc */
-/* the following deal with IEEE single-precision numbers */
-#define EXCESS 126
-#define SIGNBIT ((unsigned long)0x80000000)
-#define HIDDEN (unsigned long)(1 << 23)
-#define SIGN(fp) ((fp >> (8*sizeof(fp)-1)) & 1)
-#define EXP(fp) (((fp) >> 23) & (unsigned int)0x00FF)
-#define MANT(fp) (((fp) & (unsigned long)0x007FFFFF) | HIDDEN)
-#define PACK(s,e,m) ((s) | ((e) << 23) | (m))
+#include <float.h>
union float_long
{
};
/* divide two floats */
-float
-__fsdiv (float a1, float a2)
+float __fsdiv (float a1, float a2)
{
volatile union float_long fl1, fl2;
volatile long result;
result &= ~HIDDEN;
/* pack up and go home */
- fl1.l = PACK (sign, (unsigned long) exp, result);
+ fl1.l = PACK (sign ? 1<<31 : 0, (unsigned long) exp, result);
return (fl1.f);
}
+
** I would appreciate receiving any updates/patches/changes that anyone
** makes, and am willing to be the repository for said changes (am I
** making a big mistake?).
-
-Warning! Only single-precision is actually implemented. This file
-won't really be much use until double-precision is supported.
-
-However, once that is done, this file might eventually become a
-replacement for libgcc1.c. It might also make possible
-cross-compilation for an IEEE target machine from a non-IEEE
-host such as a VAX.
-
-If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu.
-
-
**
** Pat Wood
** Pipeline Associates, Inc.
** pipeline!phw@motown.com or
** sun!pipeline!phw or
** uunet!motown!pipeline!phw
-**
-** 05/01/91 -- V1.0 -- first release to gcc mailing lists
-** 05/04/91 -- V1.1 -- added float and double prototypes and return values
-** -- fixed problems with adding and subtracting zero
-** -- fixed rounding in truncdfsf2
-** -- fixed SWAP define and tested on 386
*/
-/*
-** The following are routines that replace the libgcc soft floating point
-** routines that are called automatically when -msoft-float is selected.
-** The support single and double precision IEEE format, with provisions
-** for byte-swapped machines (tested on 386). Some of the double-precision
-** routines work at full precision, but most of the hard ones simply punt
-** and call the single precision routines, producing a loss of accuracy.
-** long long support is not assumed or included.
-** Overall accuracy is close to IEEE (actually 68882) for single-precision
-** arithmetic. I think there may still be a 1 in 1000 chance of a bit
-** being rounded the wrong way during a multiply. I'm not fussy enough to
-** bother with it, but if anyone is, knock yourself out.
-**
-** Efficiency has only been addressed where it was obvious that something
-** would make a big difference. Anyone who wants to do this right for
-** best speed should go in and rewrite in assembler.
-**
-** I have tested this only on a 68030 workstation and 386/ix integrated
-** in with -msoft-float.
-*/
+/* (c)2000/2001: hacked a little by johan.knol@iduna.nl for sdcc */
-/* the following deal with IEEE single-precision numbers */
-#define EXCESS 126
-#define SIGNBIT ((unsigned long)0x80000000)
-#define HIDDEN (unsgined long)(1 << 23)
-#define SIGN(fp) ((fp >> (8*sizeof(fp)-1)) & 1)
-#define EXP(fp) (((fp) >> 23) & (unsigned int)0x00FF)
-#define MANT(fp) (((fp) & (unsigned long)0x007FFFFF) | HIDDEN)
-#define PACK(s,e,m) ((s) | ((e) << 23) | (m))
+#include <float.h>
union float_long
{
fl1.f = a1;
fl2.f = a2;
- if (SIGN (fl1.l) && SIGN (fl2.l))
- {
- fl1.l ^= SIGNBIT;
- fl2.l ^= SIGNBIT;
- }
if (fl1.l == fl2.l)
return (1);
return (0);
}
+
** I would appreciate receiving any updates/patches/changes that anyone
** makes, and am willing to be the repository for said changes (am I
** making a big mistake?).
-
-Warning! Only single-precision is actually implemented. This file
-won't really be much use until double-precision is supported.
-
-However, once that is done, this file might eventually become a
-replacement for libgcc1.c. It might also make possible
-cross-compilation for an IEEE target machine from a non-IEEE
-host such as a VAX.
-
-If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu.
-
-
**
** Pat Wood
** Pipeline Associates, Inc.
** pipeline!phw@motown.com or
** sun!pipeline!phw or
** uunet!motown!pipeline!phw
-**
-** 05/01/91 -- V1.0 -- first release to gcc mailing lists
-** 05/04/91 -- V1.1 -- added float and double prototypes and return values
-** -- fixed problems with adding and subtracting zero
-** -- fixed rounding in truncdfsf2
-** -- fixed SWAP define and tested on 386
*/
-/*
-** The following are routines that replace the libgcc soft floating point
-** routines that are called automatically when -msoft-float is selected.
-** The support single and double precision IEEE format, with provisions
-** for byte-swapped machines (tested on 386). Some of the double-precision
-** routines work at full precision, but most of the hard ones simply punt
-** and call the single precision routines, producing a loss of accuracy.
-** long long support is not assumed or included.
-** Overall accuracy is close to IEEE (actually 68882) for single-precision
-** arithmetic. I think there may still be a 1 in 1000 chance of a bit
-** being rounded the wrong way during a multiply. I'm not fussy enough to
-** bother with it, but if anyone is, knock yourself out.
-**
-** Efficiency has only been addressed where it was obvious that something
-** would make a big difference. Anyone who wants to do this right for
-** best speed should go in and rewrite in assembler.
-**
-** I have tested this only on a 68030 workstation and 386/ix integrated
-** in with -msoft-float.
-*/
+/* (c)2000/2001: hacked a little by johan.knol@iduna.nl for sdcc */
-/* the following deal with IEEE single-precision numbers */
-#define EXCESS 126
-#define SIGNBIT ((unsigned long)0x80000000)
-#define HIDDEN (unsigned long)(1 << 23)
-#define SIGN(fp) ((fp >> (8*sizeof(fp)-1)) & 1)
-#define EXP(fp) (((fp) >> 23) & (unsigned int) 0x00FF)
-#define MANT(fp) (((fp) & (unsigned long) 0x007FFFFF) | HIDDEN)
-#define PACK(s,e,m) ((s) | ((e) << 23) | (m))
+#include <float.h>
union float_long
{
};
/* compare two floats */
-char
-__fsgt (float a1, float a2)
+char __fsgt (float a1, float a2)
{
volatile union float_long fl1, fl2;
fl1.f = a1;
fl2.f = a2;
- if (SIGN (fl1.l) && SIGN (fl2.l))
+ if (fl1.l<0 && fl2.l<0)
{
fl1.l ^= SIGNBIT;
fl2.l ^= SIGNBIT;
** I would appreciate receiving any updates/patches/changes that anyone
** makes, and am willing to be the repository for said changes (am I
** making a big mistake?).
-
-Warning! Only single-precision is actually implemented. This file
-won't really be much use until double-precision is supported.
-
-However, once that is done, this file might eventually become a
-replacement for libgcc1.c. It might also make possible
-cross-compilation for an IEEE target machine from a non-IEEE
-host such as a VAX.
-
-If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu.
-
-
**
** Pat Wood
** Pipeline Associates, Inc.
** pipeline!phw@motown.com or
** sun!pipeline!phw or
** uunet!motown!pipeline!phw
-**
-** 05/01/91 -- V1.0 -- first release to gcc mailing lists
-** 05/04/91 -- V1.1 -- added float and double prototypes and return values
-** -- fixed problems with adding and subtracting zero
-** -- fixed rounding in truncdfsf2
-** -- fixed SWAP define and tested on 386
*/
-/*
-** The following are routines that replace the libgcc soft floating point
-** routines that are called automatically when -msoft-float is selected.
-** The support single and double precision IEEE format, with provisions
-** for byte-swapped machines (tested on 386). Some of the double-precision
-** routines work at full precision, but most of the hard ones simply punt
-** and call the single precision routines, producing a loss of accuracy.
-** long long support is not assumed or included.
-** Overall accuracy is close to IEEE (actually 68882) for single-precision
-** arithmetic. I think there may still be a 1 in 1000 chance of a bit
-** being rounded the wrong way during a multiply. I'm not fussy enough to
-** bother with it, but if anyone is, knock yourself out.
-**
-** Efficiency has only been addressed where it was obvious that something
-** would make a big difference. Anyone who wants to do this right for
-** best speed should go in and rewrite in assembler.
-**
-** I have tested this only on a 68030 workstation and 386/ix integrated
-** in with -msoft-float.
-*/
+/* (c)2000/2001: hacked a little by johan.knol@iduna.nl for sdcc */
-/* the following deal with IEEE single-precision numbers */
-#define EXCESS 126
-#define SIGNBIT ((unsigned long)0x80000000)
-#define HIDDEN (unsgined long)(1 << 23)
-#define SIGN(fp) ((fp >> (8*sizeof(fp)-1)) & 1)
-#define EXP(fp) (((fp) >> 23) & (unsigned int)0x00FF)
-#define MANT(fp) (((fp) & (unsigned long)0x007FFFFF) | HIDDEN)
-#define PACK(s,e,m) ((s) | ((e) << 23) | (m))
+#include <float.h>
union float_long
{
};
/* compare two floats */
-char
-__fslt (float a1, float a2)
+char __fslt (float a1, float a2)
{
volatile union float_long fl1, fl2;
fl1.f = a1;
fl2.f = a2;
- if (SIGN (fl1.l) && SIGN (fl2.l))
+ if (fl1.l<0 && fl2.l<0)
{
fl1.l ^= SIGNBIT;
fl2.l ^= SIGNBIT;
** I would appreciate receiving any updates/patches/changes that anyone
** makes, and am willing to be the repository for said changes (am I
** making a big mistake?).
-
-Warning! Only single-precision is actually implemented. This file
-won't really be much use until double-precision is supported.
-
-However, once that is done, this file might eventually become a
-replacement for libgcc1.c. It might also make possible
-cross-compilation for an IEEE target machine from a non-IEEE
-host such as a VAX.
-
-If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu.
-
-
**
** Pat Wood
** Pipeline Associates, Inc.
** pipeline!phw@motown.com or
** sun!pipeline!phw or
** uunet!motown!pipeline!phw
-**
-** 05/01/91 -- V1.0 -- first release to gcc mailing lists
-** 05/04/91 -- V1.1 -- added float and double prototypes and return values
-** -- fixed problems with adding and subtracting zero
-** -- fixed rounding in truncdfsf2
-** -- fixed SWAP define and tested on 386
-*/
-
-/*
-** The following are routines that replace the libgcc soft floating point
-** routines that are called automatically when -msoft-float is selected.
-** The support single and double precision IEEE format, with provisions
-** for byte-swapped machines (tested on 386). Some of the double-precision
-** routines work at full precision, but most of the hard ones simply punt
-** and call the single precision routines, producing a loss of accuracy.
-** long long support is not assumed or included.
-** Overall accuracy is close to IEEE (actually 68882) for single-precision
-** arithmetic. I think there may still be a 1 in 1000 chance of a bit
-** being rounded the wrong way during a multiply. I'm not fussy enough to
-** bother with it, but if anyone is, knock yourself out.
-**
-** Efficiency has only been addressed where it was obvious that something
-** would make a big difference. Anyone who wants to do this right for
-** best speed should go in and rewrite in assembler.
-**
-** I have tested this only on a 68030 workstation and 386/ix integrated
-** in with -msoft-float.
*/
-/* the following deal with IEEE single-precision numbers */
-#define EXCESS 126
-#define SIGNBIT ((unsigned long)0x80000000)
-#define HIDDEN (unsigned long)(1 << 23)
-#define SIGN(fp) ((fp >> (8*sizeof(fp)-1)) & 1)
-#define EXP(fp) (((fp) >> 23) & (unsigned int) 0x00FF)
-#define MANT(fp) (((fp) & (unsigned long)0x007FFFFF) | HIDDEN)
-#define PACK(s,e,m) ((s) | ((e) << 23) | (m))
+/* (c)2000/2001: hacked a little by johan.knol@iduna.nl for sdcc */
-/* the following deal with IEEE double-precision numbers */
-#define EXCESSD 1022
-#define HIDDEND (1 << 20)
-#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
-#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
-#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \
- (fp.l.lower >> 22))
+#include <float.h>
union float_long
{
float f;
- long l;
+ unsigned long l;
};
/* multiply two floats */
-float
-__fsmul (float a1, float a2)
-{
+float __fsmul (float a1, float a2) {
volatile union float_long fl1, fl2;
volatile unsigned long result;
volatile int exp;
char sign;
-
+
fl1.f = a1;
fl2.f = a2;
result += ((fl1.l & (unsigned long) 0xFF) * (fl2.l >> 8)) >> 8;
result += ((fl2.l & (unsigned long) 0xFF) * (fl1.l >> 8)) >> 8;
- if (result & (unsigned long)0x80000000)
+ if (result & SIGNBIT)
{
/* round */
result += 0x80;
result &= ~HIDDEN;
/* pack up and go home */
- fl1.l = PACK (sign ? ((unsigned long) 0x80000000) : 0 , (unsigned long)exp, result);
+ fl1.l = PACK (sign ? SIGNBIT : 0 , (unsigned long)exp, result);
return (fl1.f);
}
+
+
+
+
** I would appreciate receiving any updates/patches/changes that anyone
** makes, and am willing to be the repository for said changes (am I
** making a big mistake?).
-
-Warning! Only single-precision is actually implemented. This file
-won't really be much use until double-precision is supported.
-
-However, once that is done, this file might eventually become a
-replacement for libgcc1.c. It might also make possible
-cross-compilation for an IEEE target machine from a non-IEEE
-host such as a VAX.
-
-If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu.
-
-
**
** Pat Wood
** Pipeline Associates, Inc.
** pipeline!phw@motown.com or
** sun!pipeline!phw or
** uunet!motown!pipeline!phw
-**
-** 05/01/91 -- V1.0 -- first release to gcc mailing lists
-** 05/04/91 -- V1.1 -- added float and double prototypes and return values
-** -- fixed problems with adding and subtracting zero
-** -- fixed rounding in truncdfsf2
-** -- fixed SWAP define and tested on 386
*/
-/*
-** The following are routines that replace the libgcc soft floating point
-** routines that are called automatically when -msoft-float is selected.
-** The support single and double precision IEEE format, with provisions
-** for byte-swapped machines (tested on 386). Some of the double-precision
-** routines work at full precision, but most of the hard ones simply punt
-** and call the single precision routines, producing a loss of accuracy.
-** long long support is not assumed or included.
-** Overall accuracy is close to IEEE (actually 68882) for single-precision
-** arithmetic. I think there may still be a 1 in 1000 chance of a bit
-** being rounded the wrong way during a multiply. I'm not fussy enough to
-** bother with it, but if anyone is, knock yourself out.
-**
-** Efficiency has only been addressed where it was obvious that something
-** would make a big difference. Anyone who wants to do this right for
-** best speed should go in and rewrite in assembler.
-**
-** I have tested this only on a 68030 workstation and 386/ix integrated
-** in with -msoft-float.
-*/
+/* (c)2000/2001: hacked a little by johan.knol@iduna.nl for sdcc */
-/* the following deal with IEEE single-precision numbers */
-#define EXCESS 126
-#define SIGNBIT ((unsigned long)0x80000000)
-#define HIDDEN (unsigned long)(1 << 23)
-#define SIGN(fp) ((fp >> (8*sizeof(fp)-1)) & 1)
-#define EXP(fp) (((fp) >> 23) & (unsigned int) 0x00FF)
-#define MANT(fp) (((fp) & (unsigned long) 0x007FFFFF) | HIDDEN)
-#define PACK(s,e,m) ((s) | ((e) << 23) | (m))
+#include <float.h>
union float_long
{
};
/* compare two floats */
-char
-__fsneq (float a1, float a2)
+char __fsneq (float a1, float a2)
{
volatile union float_long fl1, fl2;
fl1.f = a1;
fl2.f = a2;
- if (SIGN (fl1.l) && SIGN (fl2.l))
+ if (fl1.l<0 && fl2.l<0)
{
fl1.l ^= SIGNBIT;
fl2.l ^= SIGNBIT;
** I would appreciate receiving any updates/patches/changes that anyone
** makes, and am willing to be the repository for said changes (am I
** making a big mistake?).
-
-Warning! Only single-precision is actually implemented. This file
-won't really be much use until double-precision is supported.
-
-However, once that is done, this file might eventually become a
-replacement for libgcc1.c. It might also make possible
-cross-compilation for an IEEE target machine from a non-IEEE
-host such as a VAX.
-
-If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu.
-
-
**
** Pat Wood
** Pipeline Associates, Inc.
** pipeline!phw@motown.com or
** sun!pipeline!phw or
** uunet!motown!pipeline!phw
-**
-** 05/01/91 -- V1.0 -- first release to gcc mailing lists
-** 05/04/91 -- V1.1 -- added float and double prototypes and return values
-** -- fixed problems with adding and subtracting zero
-** -- fixed rounding in truncdfsf2
-** -- fixed SWAP define and tested on 386
-*/
-
-/*
-** The following are routines that replace the libgcc soft floating point
-** routines that are called automatically when -msoft-float is selected.
-** The support single and double precision IEEE format, with provisions
-** for byte-swapped machines (tested on 386). Some of the double-precision
-** routines work at full precision, but most of the hard ones simply punt
-** and call the single precision routines, producing a loss of accuracy.
-** long long support is not assumed or included.
-** Overall accuracy is close to IEEE (actually 68882) for single-precision
-** arithmetic. I think there may still be a 1 in 1000 chance of a bit
-** being rounded the wrong way during a multiply. I'm not fussy enough to
-** bother with it, but if anyone is, knock yourself out.
-**
-** Efficiency has only been addressed where it was obvious that something
-** would make a big difference. Anyone who wants to do this right for
-** best speed should go in and rewrite in assembler.
-**
-** I have tested this only on a 68030 workstation and 386/ix integrated
-** in with -msoft-float.
*/
-/* the following deal with IEEE single-precision numbers */
-#define EXCESS 126
-#define SIGNBIT ((unsigned long)0x80000000)
-#define HIDDEN (unsigned long)(1 << 23)
-#define SIGN(fp) ((fp) & SIGNBIT)
-#define EXP(fp) (((fp) >> 23) & (unsigned int) 0x00FF)
-#define MANT(fp) (((fp) & (unsigned long) 0x007FFFFF) | HIDDEN)
-#define PACK(s,e,m) ((s) | ((e) << 23) | (m))
+/* (c)2000/2001: hacked a little by johan.knol@iduna.nl for sdcc */
-/* the following deal with IEEE double-precision numbers */
-#define EXCESSD 1022
-#define HIDDEND (1 << 20)
-#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
-#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
-#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \
- (fp.l.lower >> 22))
+#include <float.h>
union float_long
{
};
/* subtract two floats */
-float
-__fssub (float a1, float a2)
+float __fssub (float a1, float a2)
{
volatile union float_long fl1, fl2;
-float __slong2fs (long a );
+#include <float.h>
/* convert signed char to float */
float __schar2fs (signed char sc) {
- signed long sl=sc;
- return __slong2fs(sl);
+ return __slong2fs(sc);
}
-float __slong2fs (signed long sl);
+#include <float.h>
/* convert signed int to float */
float __sint2fs (signed int si) {
- signed long sl=si;
- return __slong2fs(sl);
+ return __slong2fs(si);
}
-float
-__ulong2fs (unsigned long a );
+#include <float.h>
/* convert signed long to float */
-float __slong2fs (signed long sl)
-{
+float __slong2fs (signed long sl) {
if (sl<0)
return -__ulong2fs(-sl);
else
-float __ulong2fs (unsigned long a );
+#include <float.h>
/* convert unsigned char to float */
float __uchar2fs (unsigned char uc) {
- unsigned long ul=uc;
- return __ulong2fs(ul);
+ return __ulong2fs(uc);
}
-float __ulong2fs (unsigned long a );
+#include <float.h>
/* convert unsigned int to float */
float __uint2fs (unsigned int ui) {
- unsigned long ul=ui;
- return __ulong2fs(ul);
+ return __ulong2fs(ui);
}
** uunet!motown!pipeline!phw
*/
-/* (c)2000: hacked a little by johan.knol@iduna.nl for sdcc */
+/* (c)2000/2001: hacked a little by johan.knol@iduna.nl for sdcc */
-/* the following deal with IEEE single-precision numbers */
-#define EXCESS 126
-#define SIGNBIT ((unsigned long)0x80000000)
-#define HIDDEN (unsigned long)(1 << 23)
-#define SIGN(fp) ((fp) & SIGNBIT)
-#define EXP(fp) (((fp) >> 23) & (unsigned int) 0x00FF)
-#define MANT(fp) (((fp) & (unsigned long)0x007FFFFF) | HIDDEN)
-#define PACK(s,e,m) ((s) | ((e) << 23) | (m))
+#include <float.h>
union float_long
{
long l;
};
-float
-__ulong2fs (unsigned long a )
+float __ulong2fs (unsigned long a )
{
int exp = 24 + EXCESS;
volatile union float_long fl;
return 0.0;
}
+ while (a & NORM)
+ {
+ // we lose accuracy here
+ a >>= 1;
+ exp++;
+ }
+
while (a < HIDDEN)
{
a <<= 1;
exp--;
}
- a &= ~HIDDEN ;
+#if 1
+ if ((a&0x7fffff)==0x7fffff) {
+ a=0;
+ exp++;
+ }
+#endif
+
+ a &= ~HIDDEN ;
/* pack up and go home */
fl.l = PACK(0,(unsigned long)exp, a);