* device/lib/pic/libsdcc/fs2ulong.c, device/lib/pic/libsdcc/fsadd.c,
[fw/sdcc] / device / lib / pic16 / libsdcc / float / fsadd.c
1 /*
2 ** libgcc support for software floating point.
3 ** Copyright (C) 1991 by Pipeline Associates, Inc.  All rights reserved.
4 ** Permission is granted to do *anything* you want with this file,
5 ** commercial or otherwise, provided this message remains intact.  So there!
6 ** I would appreciate receiving any updates/patches/changes that anyone
7 ** makes, and am willing to be the repository for said changes (am I
8 ** making a big mistake?).
9 **
10 ** Pat Wood
11 ** Pipeline Associates, Inc.
12 ** pipeline!phw@motown.com or
13 ** sun!pipeline!phw or
14 ** uunet!motown!pipeline!phw
15 */
16
17 /*
18 ** $Id$
19 */
20
21 #include <float.h>
22
23 union float_long
24   {
25     float f;
26     unsigned long l;
27   };
28
29 /* add two floats */
30 float __fsadd (float a1, float a2) _FS_REENTRANT
31 {
32   volatile union float_long fl1, fl2;
33   long mant1, mant2;
34   int exp1, exp2;
35   unsigned long sign = 0;
36
37   fl1.f = a1;
38   fl2.f = a2;
39
40   /* check for zero args */
41   if (!fl1.l)
42     return (fl2.f);
43   if (!fl2.l)
44     return (fl1.f);
45
46   exp1 = EXP (fl1.l);
47   exp2 = EXP (fl2.l);
48
49   if (exp1 > exp2 + 25)
50     return (fl1.f);
51   if (exp2 > exp1 + 25)
52     return (fl2.f);
53
54   mant1 = MANT (fl1.l);
55   mant2 = MANT (fl2.l);
56
57   if (SIGN (fl1.l))
58     mant1 = -mant1;
59   if (SIGN (fl2.l))
60     mant2 = -mant2;
61
62   if (exp1 > exp2)
63     {
64       mant2 >>= exp1 - exp2;
65     }
66   else
67     {
68       mant1 >>= exp2 - exp1;
69       exp1 = exp2;
70     }
71   mant1 += mant2;
72
73   if (mant1 < 0)
74     {
75       mant1 = -mant1;
76       sign = SIGNBIT;
77     }
78   else if (!mant1)
79     return (0);
80
81   /* normalize */
82   while (mant1<HIDDEN) {
83     mant1 <<= 1;
84     exp1--;
85   }
86
87   /* round off */
88   while (mant1 & 0xff000000) {
89     if (mant1&1)
90       mant1 += 2;
91     mant1 >>= 1 ;
92     exp1++;
93   }
94
95   /* turn off hidden bit */
96   mant1 &= ~HIDDEN;
97
98   /* pack up and go home */
99   fl1.l = PACK (sign, (unsigned long) exp1, mant1);
100
101   return (fl1.f);
102 }