* sim/ucsim/hc08.src/inst.cc,
[fw/sdcc] / device / lib / _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 #include <float.h>
18
19 union float_long
20   {
21     float f;
22     unsigned long l;
23   };
24
25 /* add two floats */
26 float __fsadd (float a1, float a2)
27 {
28   volatile long mant1, mant2;
29   volatile union float_long fl1, fl2;
30   volatile int exp1, exp2;
31   volatile unsigned long sign = 0;
32
33   fl1.f = a1;
34   fl2.f = a2;
35
36   /* check for zero args */
37   if (!fl1.l)
38     return (fl2.f);
39   if (!fl2.l)
40     return (fl1.f);
41
42   exp1 = EXP (fl1.l);
43   exp2 = EXP (fl2.l);
44
45   if (exp1 > exp2 + 25)
46     return (fl1.f);
47   if (exp2 > exp1 + 25)
48     return (fl2.f);
49
50   mant1 = MANT (fl1.l);
51   mant2 = MANT (fl2.l);
52
53   if (SIGN (fl1.l))
54     mant1 = -mant1;
55   if (SIGN (fl2.l))
56     mant2 = -mant2;
57
58   if (exp1 > exp2)
59     {
60       mant2 >>= exp1 - exp2;
61     }
62   else
63     {
64       mant1 >>= exp2 - exp1;
65       exp1 = exp2;
66     }
67   mant1 += mant2;
68
69   if (mant1 < 0)
70     {
71       mant1 = -mant1;
72       sign = SIGNBIT;
73     }
74   else if (!mant1)
75     return (0);
76
77   /* normalize */
78   while (mant1<HIDDEN) {
79     mant1 <<= 1;
80     exp1--;
81   }
82
83   /* round off */
84   while (mant1 & 0xff000000) {
85     if (mant1&1)
86       mant1 += 2;
87     mant1 >>= 1 ;
88     exp1++;
89   }
90
91   /* turn off hidden bit */
92   mant1 &= ~HIDDEN;
93
94   /* pack up and go home */
95   fl1.l = PACK (sign, (unsigned long) exp1, mant1);
96
97   return (fl1.f);
98 }