⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fpgnulib.c

📁 gcc3.2.1源代码
💻 C
字号:
/* This is a stripped down version of floatlib.c.  It supplies only those   functions which exist in libgcc, but for which there is not assembly   language versions in m68k/lb1sf68.asm.   It also includes simplistic support for extended floats (by working in   double precision).  You must compile this file again with -DEXTFLOAT   to get this support.  *//*** gnulib 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**** 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 gnulib 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		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		1022#define HIDDEND		(1L << 20L)#define EXPDBITS	11#define EXPDMASK	0x7FF#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	0xFFFFF /* mask of upper part *//* the following deal with IEEE extended-precision numbers */#define EXCESSX		16382#define HIDDENX		(1L << 31L)#define EXPXBITS	15#define EXPXMASK	0x7FFF#define EXPX(fp)	(((fp.l.upper) >> 16) & EXPXMASK)#define SIGNX(fp)	((fp.l.upper) & SIGNBIT)#define MANTXMASK	0x7FFFFFFF /* mask of upper part */union double_long {  double d;  struct {      long upper;      unsigned long lower;    } l;};union float_long {  float f;  long l;};union long_double_long{  long double ld;  struct    {      long upper;      unsigned long middle;      unsigned long lower;    } l;};#ifndef EXTFLOAT/* convert int to double */double__floatsidf (int 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 = -a1;      if (a1 < 0)	{	  dl.l.upper = SIGNBIT | ((32 + EXCESSD) << 20L);	  dl.l.lower = 0;	  return dl.d;        }    }  while (a1 < 0x1000000)    {      a1 <<= 4;      exp -= 4;    }  while (a1 < 0x40000000)    {      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 int to float */float__floatsisf (int l){  double foo = __floatsidf (l);  return foo;}/* convert float to double */double__extendsfdf2 (float a1){  register union float_long fl1;  register union double_long dl;  register long exp;  fl1.f = a1;  if (!fl1.l)    {      dl.l.upper = dl.l.lower = 0;      return dl.d;    }  dl.l.upper = SIGN (fl1.l);  exp = EXP (fl1.l) - EXCESS + EXCESSD;  dl.l.upper |= exp << 20;  dl.l.upper |= (MANT (fl1.l) & ~HIDDEN) >> 3;  dl.l.lower = MANT (fl1.l) << 29;	  return dl.d;}/* convert double to float */float__truncdfsf2 (double a1){  register long exp;  register long mant;  register union float_long fl;  register union double_long dl1;  dl1.d = a1;  if (!dl1.l.upper && !dl1.l.lower)    return 0;  exp = EXPD (dl1) - EXCESSD + EXCESS;  /* shift double mantissa 6 bits so we can round */  mant = MANTD (dl1) >> 6;  /* now round and shift down */  mant += 1;  mant >>= 1;  /* did the round overflow? */  if (mant & 0xFF000000)    {      mant >>= 1;      exp++;    }  mant &= ~HIDDEN;  /* pack up and go home */  fl.l = PACK (SIGND (dl1), exp, mant);  return (fl.f);}/* convert double to int */int__fixdfsi (double a1){  register union double_long dl1;  register long exp;  register long l;  dl1.d = a1;  if (!dl1.l.upper && !dl1.l.lower)     return 0;  exp = EXPD (dl1) - EXCESSD - 31;  l = MANTD (dl1);  if (exp > 0)     {      /* Return largest integer.  */      return SIGND (dl1) ? 0x80000000 : 0x7fffffff;    }  if (exp <= -32)    return 0;  /* shift down until exp = 0 */  if (exp < 0)    l >>= -exp;  return (SIGND (dl1) ? -l : l);}/* convert float to int */int__fixsfsi (float a1){  double foo = a1;  return __fixdfsi (foo);}#else /* EXTFLOAT *//* Primitive extended precision floating point support.   We assume all numbers are normalized, don't do any rounding, etc.  *//* Prototypes for the above in case we use them.  */double __floatsidf (int);float __floatsisf (int);double __extendsfdf2 (float);float __truncdfsf2 (double);int __fixdfsi (double);int __fixsfsi (float);/* convert double to long double */long double__extenddfxf2 (double d){  register union double_long dl;  register union long_double_long ldl;  register long exp;  dl.d = d;  /*printf ("dfxf in: %g\n", d);*/  if (!dl.l.upper && !dl.l.lower)    return 0;  ldl.l.upper = SIGND (dl);  exp = EXPD (dl) - EXCESSD + EXCESSX;  ldl.l.upper |= exp << 16;  ldl.l.middle = HIDDENX;  /* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */  ldl.l.middle |= (dl.l.upper & MANTDMASK) << (31 - 20);  /* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */  ldl.l.middle |= dl.l.lower >> (1 + 20);  /* 32 - 21: # bits of dl.l.lower in ldl.l.middle */  ldl.l.lower = dl.l.lower << (32 - 21);  /*printf ("dfxf out: %s\n", dumpxf (ldl.ld));*/  return ldl.ld;}/* convert long double to double */double__truncxfdf2 (long double ld){  register long exp;  register union double_long dl;  register union long_double_long ldl;  ldl.ld = ld;  /*printf ("xfdf in: %s\n", dumpxf (ld));*/  if (!ldl.l.upper && !ldl.l.middle && !ldl.l.lower)    return 0;  exp = EXPX (ldl) - EXCESSX + EXCESSD;  /* ??? quick and dirty: keep `exp' sane */  if (exp >= EXPDMASK)    exp = EXPDMASK - 1;  dl.l.upper = SIGNX (ldl);  dl.l.upper |= exp << (32 - (EXPDBITS + 1));  /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */  dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1);  dl.l.lower = (ldl.l.middle & MANTXMASK) << (32 - (EXPDBITS + 1 - 1));  dl.l.lower |= ldl.l.lower >> (EXPDBITS + 1 - 1);  /*printf ("xfdf out: %g\n", dl.d);*/  return dl.d;}/* convert a float to a long double */long double__extendsfxf2 (float f){  long double foo = __extenddfxf2 (__extendsfdf2 (f));  return foo;}/* convert a long double to a float */float__truncxfsf2 (long double ld){  float foo = __truncdfsf2 (__truncxfdf2 (ld));  return foo;}/* convert an int to a long double */long double__floatsixf (int l){  double foo = __floatsidf (l);  return foo;}/* convert a long double to an int */int__fixxfsi (long double ld){  int foo = __fixdfsi ((double) ld);  return foo;}/* The remaining provide crude math support by working in double precision.  */long double__addxf3 (long double x1, long double x2){  return (double) x1 + (double) x2;}long double__subxf3 (long double x1, long double x2){  return (double) x1 - (double) x2;}long double__mulxf3 (long double x1, long double x2){  return (double) x1 * (double) x2;}long double__divxf3 (long double x1, long double x2){  return (double) x1 / (double) x2;}long double__negxf2 (long double x1){  return - (double) x1;}long__cmpxf2 (long double x1, long double x2){  return __cmpdf2 ((double) x1, (double) x2);}long__eqxf2 (long double x1, long double x2){  return __cmpdf2 ((double) x1, (double) x2);}long__nexf2 (long double x1, long double x2){  return __cmpdf2 ((double) x1, (double) x2);}long__ltxf2 (long double x1, long double x2){  return __cmpdf2 ((double) x1, (double) x2);}long__lexf2 (long double x1, long double x2){  return __cmpdf2 ((double) x1, (double) x2);}long__gtxf2 (long double x1, long double x2){  return __cmpdf2 ((double) x1, (double) x2);}long__gexf2 (long double x1, long double x2){  return __cmpdf2 ((double) x1, (double) x2);}#endif /* EXTFLOAT */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -