beb6607d216a8cb8878071b376dca4fee173d355
[fw/sdcc] / device / lib / pic / libsdcc / fsdiv.c
1 /*\r
2 ** libgcc support for software floating point.\r
3 ** Copyright (C) 1991 by Pipeline Associates, Inc.  All rights reserved.\r
4 ** Permission is granted to do *anything* you want with this file,\r
5 ** commercial or otherwise, provided this message remains intact.  So there!\r
6 ** I would appreciate receiving any updates/patches/changes that anyone\r
7 ** makes, and am willing to be the repository for said changes (am I\r
8 ** making a big mistake?).\r
9 **\r
10 ** Pat Wood\r
11 ** Pipeline Associates, Inc.\r
12 ** pipeline!phw@motown.com or\r
13 ** sun!pipeline!phw or\r
14 ** uunet!motown!pipeline!phw\r
15 */\r
16 \r
17 /*\r
18 ** $Id: fsdiv.c 3513 2004-10-01 14:49:51Z vrokas $\r
19 */\r
20 \r
21 /* (c)2000/2001: hacked a little by johan.knol@iduna.nl for sdcc */\r
22 \r
23 #include <float.h>\r
24 \r
25 union float_long\r
26   {\r
27     float f;\r
28     long l;\r
29   };\r
30 \r
31 /* divide two floats */\r
32 float __fsdiv (float a1, float a2) _FS_REENTRANT\r
33 {\r
34   FS_STATIC volatile union float_long fl1, fl2;\r
35   long result;\r
36   unsigned long mask;\r
37   long mant1, mant2;\r
38   int exp ;\r
39   char sign;\r
40 \r
41   fl1.f = a1;\r
42   fl2.f = a2;\r
43 \r
44   /* subtract exponents */\r
45   exp = EXP (fl1.l) ;\r
46   exp -= EXP (fl2.l);\r
47   exp += EXCESS;\r
48 \r
49   /* compute sign */\r
50   sign = SIGN (fl1.l) ^ SIGN (fl2.l);\r
51 \r
52   /* divide by zero??? */\r
53   if (!fl2.l)\r
54     {/* return NaN or -NaN */\r
55       fl2.l = 0x7FC00000;\r
56       return (fl2.f);\r
57     }\r
58 \r
59   /* numerator zero??? */\r
60   if (!fl1.l)\r
61     return (0);\r
62 \r
63   /* now get mantissas */\r
64   mant1 = MANT (fl1.l);\r
65   mant2 = MANT (fl2.l);\r
66 \r
67   /* this assures we have 25 bits of precision in the end */\r
68   if (mant1 < mant2)\r
69     {\r
70       mant1 <<= 1;\r
71       exp--;\r
72     }\r
73 \r
74   /* now we perform repeated subtraction of fl2.l from fl1.l */\r
75   mask = 0x1000000;\r
76   result = 0;\r
77   while (mask)\r
78     {\r
79       if (mant1 >= mant2)\r
80         {\r
81           result |= mask;\r
82           mant1 -= mant2;\r
83         }\r
84       mant1 <<= 1;\r
85       mask >>= 1;\r
86     }\r
87 \r
88   /* round */\r
89   result += 1;\r
90 \r
91   /* normalize down */\r
92   exp++;\r
93   result >>= 1;\r
94 \r
95   result &= ~HIDDEN;\r
96 \r
97   /* pack up and go home */\r
98   if (exp >= 0x100)\r
99     fl1.l = (sign ? SIGNBIT : 0) | 0x7F800000;\r
100   else if (exp < 0)\r
101     fl1.l = 0;\r
102   else\r
103     fl1.l = PACK (sign ? SIGNBIT : 0 , exp, result);\r
104   return (fl1.f);\r
105 }\r
106 \r