* device/lib/pic/libm: NEW, added math library functions
[fw/sdcc] / device / lib / pic / libsdcc / fsadd.c
diff --git a/device/lib/pic/libsdcc/fsadd.c b/device/lib/pic/libsdcc/fsadd.c
new file mode 100644 (file)
index 0000000..bda1826
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+** 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
+*/
+
+/*
+** $Id: fsadd.c 3513 2004-10-01 14:49:51Z vrokas $
+*/
+
+#include <float.h>
+
+union float_long
+  {
+    float f;
+    unsigned long l;
+  };
+
+/* add two floats */
+float __fsadd (float a1, float a2) _FS_REENTRANT
+{
+  FS_STATIC volatile union float_long fl1, fl2;
+  unsigned long mant1, mant2;
+  int exp1, exp2;
+  unsigned long sign = 0;
+
+  fl1.f = a1;
+  fl2.f = a2;
+
+  /* check for zero args */
+  if (!fl1.l)
+    return (fl2.f);
+  if (!fl2.l)
+    return (fl1.f);
+
+  exp1 = EXP (fl1.l);
+  exp2 = EXP (fl2.l);
+
+  if (exp1 > exp2 + 25)
+    return (fl1.f);
+  if (exp2 > exp1 + 25)
+    return (fl2.f);
+
+  mant1 = MANT (fl1.l);
+  mant2 = MANT (fl2.l);
+
+  if (SIGN (fl1.l))
+    mant1 = -mant1;
+  if (SIGN (fl2.l))
+    mant2 = -mant2;
+
+  if (exp1 > exp2)
+    {
+      mant2 >>= exp1 - exp2;
+    }
+  else
+    {
+      mant1 >>= exp2 - exp1;
+      exp1 = exp2;
+    }
+  mant1 += mant2;
+
+  if ((long)mant1 < 0)
+    {
+      mant1 = -mant1;
+      sign = SIGNBIT;
+    }
+  else if (!mant1)
+    return (0);
+
+  /* normalize */
+  while (mant1<HIDDEN) {
+    mant1 <<= 1;
+    exp1--;
+  }
+
+  /* round off */
+  while (0 != (mant1 & 0xff000000)) {
+    if (mant1&1)
+      mant1 += 2;
+    mant1 >>= 1 ;
+    exp1++;
+  }
+
+  /* turn off hidden bit */
+  mant1 &= ~HIDDEN;
+
+  /* pack up and go home */
+  fl1.l = PACK (sign, (unsigned long) exp1, mant1);
+
+  return (fl1.f);
+}