* src/z80/ralloc.c (packRegsForHLUse): Banned IFXs from being packed into HL.
[fw/sdcc] / device / lib / _fsadd.c
1 /* the following deal with IEEE single-precision numbers */
2 #define EXCESS          126
3 #define SIGNBIT         ((unsigned long)0x80000000)
4 #define HIDDEN          (unsigned long)(1 << 23)
5 #define SIGN(fp)        ((fp >> (8*sizeof(fp)-1)) & 1) 
6 #define EXP(fp)         (((fp) >> 23) & (unsigned int)0x00FF)
7 #define MANT(fp)        (((fp) & (unsigned long)0x007FFFFF) | HIDDEN)
8 #define PACK(s,e,m)     ((s) | ((e) << 23) | (m))
9
10 union float_long
11   {
12     float f;
13     long l;
14   };
15 /* add two floats */
16 float
17 __fsadd (float a1, float a2)
18 {
19   volatile long mant1, mant2;
20   volatile union float_long fl1, fl2;
21   volatile int exp1, exp2;
22   volatile unsigned long sign = 0;
23
24   fl1.f = a1;
25   fl2.f = a2;
26
27   /* check for zero args */
28   if (!fl1.l)
29     return (fl2.f);
30   if (!fl2.l)
31     return (fl1.f);
32
33   exp1 = EXP (fl1.l);
34   exp2 = EXP (fl2.l);
35
36   if (exp1 > exp2 + 25)
37     return (fl1.f);
38   if (exp2 > exp1 + 25)
39     return (fl2.f);
40
41   /* do everything in excess precision so's we can round later */
42   mant1 = MANT (fl1.l) << 6;
43   mant2 = MANT (fl2.l) << 6;
44
45   if (SIGN (fl1.l))
46     mant1 = -mant1;
47   if (SIGN (fl2.l))
48     mant2 = -mant2;
49
50   if (exp1 > exp2)
51     {
52       mant2 >>= exp1 - exp2;
53     }
54   else
55     {
56       mant1 >>= exp2 - exp1;
57       exp1 = exp2;
58     }
59   mant1 += mant2;
60
61   if (mant1 < 0)
62     {
63       mant1 = -mant1;
64       sign = SIGNBIT;
65     }
66   else if (!mant1)
67     return (0);
68
69   /* normalize up */
70   while (!((unsigned long)mant1 & (unsigned long) 0xE0000000))
71     {
72       mant1 <<= 1;
73       exp1--;
74     }
75
76   /* normalize down? */
77   if ((unsigned long)mant1 & (unsigned long)(1 << 30))
78     {
79       mant1 >>= 1 ;
80       exp1++;
81     }
82
83   /* round to even */
84   mant1 += (mant1 & (unsigned long)0x40) ? (unsigned long) 0x20 : (unsigned long) 0x1F;
85
86   /* normalize down? */
87   if (mant1 & (unsigned long)(1 << 30))
88     {
89       mant1 >>= 1;
90       exp1++;
91     }
92
93   /* lose extra precision */
94   mant1 >>= 6;
95
96   /* turn off hidden bit */
97   mant1 = (unsigned long)mant1 & ~HIDDEN;
98
99   /* pack up and go home */
100   fl1.l = PACK (sign, (unsigned long) exp1, mant1);
101   return (fl1.f);
102 }