3b07ce92d61bc0474ef3d2df845c0ea8471913d4
[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)
31 // reentrant
32 {
33   volatile long mant1, mant2;
34   volatile union float_long fl1, fl2;
35   volatile int exp1, exp2;
36   volatile unsigned long sign = 0;
37
38   fl1.f = a1;
39   fl2.f = a2;
40
41   /* check for zero args */
42   if (!fl1.l)
43     return (fl2.f);
44   if (!fl2.l)
45     return (fl1.f);
46
47   exp1 = EXP (fl1.l);
48   exp2 = EXP (fl2.l);
49
50   if (exp1 > exp2 + 25)
51     return (fl1.f);
52   if (exp2 > exp1 + 25)
53     return (fl2.f);
54
55   mant1 = MANT (fl1.l);
56   mant2 = MANT (fl2.l);
57
58   if (SIGN (fl1.l))
59     mant1 = -mant1;
60   if (SIGN (fl2.l))
61     mant2 = -mant2;
62
63   if (exp1 > exp2)
64     {
65       mant2 >>= exp1 - exp2;
66     }
67   else
68     {
69       mant1 >>= exp2 - exp1;
70       exp1 = exp2;
71     }
72   mant1 += mant2;
73
74   if (mant1 < 0)
75     {
76       mant1 = -mant1;
77       sign = SIGNBIT;
78     }
79   else if (!mant1)
80     return (0);
81
82   /* normalize */
83   while (mant1<HIDDEN) {
84     mant1 <<= 1;
85     exp1--;
86   }
87
88   /* round off */
89   while (mant1 & 0xff000000) {
90     if (mant1&1)
91       mant1 += 2;
92     mant1 >>= 1 ;
93     exp1++;
94   }
95
96   /* turn off hidden bit */
97   mant1 &= ~HIDDEN;
98
99   /* pack up and go home */
100   fl1.l = PACK (sign, (unsigned long) exp1, mant1);
101
102   return (fl1.f);
103 }