fixed and cleaned up fp support, optimisation yet to come
[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 /* (c)2000/2001: hacked a little by johan.knol@iduna.nl for sdcc */
18
19 #include <float.h>
20
21 union float_long
22   {
23     float f;
24     unsigned long l;
25   };
26
27 /* add two floats */
28 float __fsadd (float a1, float a2)
29 {
30   volatile long mant1, mant2;
31   volatile union float_long fl1, fl2;
32   volatile int exp1, exp2;
33   volatile unsigned long sign = 0;
34
35   fl1.f = a1;
36   fl2.f = a2;
37
38   /* check for zero args */
39   if (!fl1.l)
40     return (fl2.f);
41   if (!fl2.l)
42     return (fl1.f);
43
44   exp1 = EXP (fl1.l);
45   exp2 = EXP (fl2.l);
46
47   if (exp1 > exp2 + 25)
48     return (fl1.f);
49   if (exp2 > exp1 + 25)
50     return (fl2.f);
51
52   mant1 = MANT (fl1.l);
53   mant2 = MANT (fl2.l);
54
55   if (SIGN (fl1.l))
56     mant1 = -mant1;
57   if (SIGN (fl2.l))
58     mant2 = -mant2;
59
60   if (exp1 > exp2)
61     {
62       mant2 >>= exp1 - exp2;
63     }
64   else
65     {
66       mant1 >>= exp2 - exp1;
67       exp1 = exp2;
68     }
69   mant1 += mant2;
70
71   if (mant1 < 0)
72     {
73       mant1 = -mant1;
74       sign = SIGNBIT;
75     }
76   else if (!mant1)
77     return (0);
78
79   /* normalize */
80   /* jwk: TODO: changing the next two whiles in nested ifs 
81      seriously breaks it. Why?????????????????? */ 
82   while (mant1<HIDDEN) {
83     mant1 <<= 1;
84     exp1--;
85   }
86
87   while (mant1 & 0xff000000) {
88     // round off
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 }