From 61da3cca8ba3e73617d60a8a50b31e541af74103 Mon Sep 17 00:00:00 2001 From: johanknol Date: Sat, 10 Nov 2001 17:50:51 +0000 Subject: [PATCH] fixed and cleaned up fp support, optimisation yet to come git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1556 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- device/include/float.h | 35 ++++++++++++++++++ device/lib/_fs2schar.c | 4 +-- device/lib/_fs2sint.c | 4 +-- device/lib/_fs2slong.c | 8 +---- device/lib/_fs2uchar.c | 4 +-- device/lib/_fs2uint.c | 2 +- device/lib/_fs2ulong.c | 16 ++------- device/lib/_fsadd.c | 82 +++++++++++++++++++++--------------------- device/lib/_fsdiv.c | 54 +++------------------------- device/lib/_fseq.c | 54 ++-------------------------- device/lib/_fsgt.c | 53 +++------------------------ device/lib/_fslt.c | 53 +++------------------------ device/lib/_fsmul.c | 72 ++++++------------------------------- device/lib/_fsneq.c | 53 +++------------------------ device/lib/_fssub.c | 59 ++---------------------------- device/lib/_schar2fs.c | 5 ++- device/lib/_sint2fs.c | 5 ++- device/lib/_slong2fs.c | 6 ++-- device/lib/_uchar2fs.c | 5 ++- device/lib/_uint2fs.c | 5 ++- device/lib/_ulong2fs.c | 30 +++++++++------- 21 files changed, 145 insertions(+), 464 deletions(-) diff --git a/device/include/float.h b/device/include/float.h index f76ba54c..328fccd8 100644 --- a/device/include/float.h +++ b/device/include/float.h @@ -24,6 +24,9 @@ #ifndef __SDC51_FLOAT_H #define __SDC51_FLOAT_H 1 + +#include + #define FLT_RADIX 2 #define FLT_MANT_DIG 24 #define FLT_EPSILON 1.192092896E-07F @@ -35,6 +38,38 @@ #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 diff --git a/device/lib/_fs2schar.c b/device/lib/_fs2schar.c index b783ea59..8ccf1ebd 100644 --- a/device/lib/_fs2schar.c +++ b/device/lib/_fs2schar.c @@ -1,6 +1,4 @@ -#include - -signed long __fs2slong (float f); +#include /* convert float to signed char */ signed char __fs2schar (float f) { diff --git a/device/lib/_fs2sint.c b/device/lib/_fs2sint.c index dd49c4e7..78c17983 100644 --- a/device/lib/_fs2sint.c +++ b/device/lib/_fs2sint.c @@ -1,6 +1,4 @@ -#include - -signed long __fs2slong (float f); +#include /* convert float to signed int */ signed int __fs2sint (float f) { diff --git a/device/lib/_fs2slong.c b/device/lib/_fs2slong.c index 1c3aec8c..236ef878 100644 --- a/device/lib/_fs2slong.c +++ b/device/lib/_fs2slong.c @@ -1,6 +1,4 @@ -#include - -unsigned long __fs2ulong (float a1); +#include /* convert float to signed long */ signed long __fs2slong (float f) { @@ -9,12 +7,8 @@ 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); } } diff --git a/device/lib/_fs2uchar.c b/device/lib/_fs2uchar.c index 68e4c679..ce4a9272 100644 --- a/device/lib/_fs2uchar.c +++ b/device/lib/_fs2uchar.c @@ -1,6 +1,4 @@ -#include - -unsigned long __fs2ulong (float a1); +#include /* convert float to unsigned char */ unsigned char __fs2uchar (float f) { diff --git a/device/lib/_fs2uint.c b/device/lib/_fs2uint.c index 464a729e..186b7f37 100644 --- a/device/lib/_fs2uint.c +++ b/device/lib/_fs2uint.c @@ -1,4 +1,4 @@ -#include +#include unsigned long __fs2ulong (float a1); diff --git a/device/lib/_fs2ulong.c b/device/lib/_fs2ulong.c index 01f55a49..0b746143 100644 --- a/device/lib/_fs2ulong.c +++ b/device/lib/_fs2ulong.c @@ -14,18 +14,9 @@ ** 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 - -/* 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 union float_long { @@ -46,9 +37,6 @@ __fs2ulong (float a1) 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); diff --git a/device/lib/_fsadd.c b/device/lib/_fsadd.c index a4273d9a..fa0970ae 100644 --- a/device/lib/_fsadd.c +++ b/device/lib/_fsadd.c @@ -1,20 +1,31 @@ -/* 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 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; @@ -38,9 +49,8 @@ __fsadd (float a1, float a2) 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; @@ -66,37 +76,27 @@ __fsadd (float a1, float a2) 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>= 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); } diff --git a/device/lib/_fsdiv.c b/device/lib/_fsdiv.c index f597027f..93a5f86d 100644 --- a/device/lib/_fsdiv.c +++ b/device/lib/_fsdiv.c @@ -6,61 +6,17 @@ ** 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 union float_long { @@ -69,8 +25,7 @@ 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; @@ -134,6 +89,7 @@ __fsdiv (float a1, float a2) 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); } + diff --git a/device/lib/_fseq.c b/device/lib/_fseq.c index fd2e8fe7..b73cd060 100644 --- a/device/lib/_fseq.c +++ b/device/lib/_fseq.c @@ -6,61 +6,17 @@ ** 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 union float_long { @@ -77,12 +33,8 @@ __fseq (float a1, float a2) 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); } + diff --git a/device/lib/_fsgt.c b/device/lib/_fsgt.c index 106df0c0..2fbbda27 100644 --- a/device/lib/_fsgt.c +++ b/device/lib/_fsgt.c @@ -6,61 +6,17 @@ ** 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 union float_long { @@ -69,15 +25,14 @@ 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; diff --git a/device/lib/_fslt.c b/device/lib/_fslt.c index e22a5ead..2e55f83a 100644 --- a/device/lib/_fslt.c +++ b/device/lib/_fslt.c @@ -6,61 +6,17 @@ ** 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 union float_long { @@ -69,15 +25,14 @@ 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; diff --git a/device/lib/_fsmul.c b/device/lib/_fsmul.c index c1507811..09fd00a4 100644 --- a/device/lib/_fsmul.c +++ b/device/lib/_fsmul.c @@ -6,85 +6,31 @@ ** 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 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; @@ -104,7 +50,7 @@ __fsmul (float a1, float 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; @@ -121,6 +67,10 @@ __fsmul (float a1, float a2) 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); } + + + + diff --git a/device/lib/_fsneq.c b/device/lib/_fsneq.c index 8d74dee7..1d23ed38 100644 --- a/device/lib/_fsneq.c +++ b/device/lib/_fsneq.c @@ -6,61 +6,17 @@ ** 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 union float_long { @@ -69,15 +25,14 @@ 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; diff --git a/device/lib/_fssub.c b/device/lib/_fssub.c index 43e10b29..b9f453fb 100644 --- a/device/lib/_fssub.c +++ b/device/lib/_fssub.c @@ -6,69 +6,17 @@ ** 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 union float_long { @@ -77,8 +25,7 @@ union float_long }; /* subtract two floats */ -float -__fssub (float a1, float a2) +float __fssub (float a1, float a2) { volatile union float_long fl1, fl2; diff --git a/device/lib/_schar2fs.c b/device/lib/_schar2fs.c index f7c90f33..2a8fb438 100644 --- a/device/lib/_schar2fs.c +++ b/device/lib/_schar2fs.c @@ -1,7 +1,6 @@ -float __slong2fs (long a ); +#include /* convert signed char to float */ float __schar2fs (signed char sc) { - signed long sl=sc; - return __slong2fs(sl); + return __slong2fs(sc); } diff --git a/device/lib/_sint2fs.c b/device/lib/_sint2fs.c index 4ee9c800..0c86277c 100644 --- a/device/lib/_sint2fs.c +++ b/device/lib/_sint2fs.c @@ -1,7 +1,6 @@ -float __slong2fs (signed long sl); +#include /* convert signed int to float */ float __sint2fs (signed int si) { - signed long sl=si; - return __slong2fs(sl); + return __slong2fs(si); } diff --git a/device/lib/_slong2fs.c b/device/lib/_slong2fs.c index 11516e4f..394fba87 100644 --- a/device/lib/_slong2fs.c +++ b/device/lib/_slong2fs.c @@ -1,9 +1,7 @@ -float -__ulong2fs (unsigned long a ); +#include /* convert signed long to float */ -float __slong2fs (signed long sl) -{ +float __slong2fs (signed long sl) { if (sl<0) return -__ulong2fs(-sl); else diff --git a/device/lib/_uchar2fs.c b/device/lib/_uchar2fs.c index 47525301..3e919882 100644 --- a/device/lib/_uchar2fs.c +++ b/device/lib/_uchar2fs.c @@ -1,7 +1,6 @@ -float __ulong2fs (unsigned long a ); +#include /* convert unsigned char to float */ float __uchar2fs (unsigned char uc) { - unsigned long ul=uc; - return __ulong2fs(ul); + return __ulong2fs(uc); } diff --git a/device/lib/_uint2fs.c b/device/lib/_uint2fs.c index 514c0211..9b443fa9 100644 --- a/device/lib/_uint2fs.c +++ b/device/lib/_uint2fs.c @@ -1,7 +1,6 @@ -float __ulong2fs (unsigned long a ); +#include /* convert unsigned int to float */ float __uint2fs (unsigned int ui) { - unsigned long ul=ui; - return __ulong2fs(ul); + return __ulong2fs(ui); } diff --git a/device/lib/_ulong2fs.c b/device/lib/_ulong2fs.c index 7ba7e11c..f3794204 100644 --- a/device/lib/_ulong2fs.c +++ b/device/lib/_ulong2fs.c @@ -14,16 +14,9 @@ ** 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 union float_long { @@ -31,8 +24,7 @@ union float_long long l; }; -float -__ulong2fs (unsigned long a ) +float __ulong2fs (unsigned long a ) { int exp = 24 + EXCESS; volatile union float_long fl; @@ -42,13 +34,27 @@ __ulong2fs (unsigned long a ) 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); -- 2.30.2