9752800c6cbfc216ebe30d06e50a3a8f7fc7e51d
[fw/sdcc] / device / lib / pic / libsdcc / fsmul.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: fsmul.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     unsigned long l;\r
29   };\r
30 \r
31 /* multiply two floats */\r
32 float __fsmul (float a1, float a2) _FS_REENTRANT\r
33 {\r
34   FS_STATIC volatile union float_long fl1, fl2;\r
35   unsigned long result;\r
36   int exp;\r
37   char sign;\r
38   \r
39   fl1.f = a1;\r
40   fl2.f = a2;\r
41 \r
42   if (!fl1.l || !fl2.l)\r
43     return (0);\r
44 \r
45   /* compute sign and exponent */\r
46   sign = SIGN (fl1.l) ^ SIGN (fl2.l);\r
47   exp = EXP (fl1.l) - EXCESS;\r
48   exp += EXP (fl2.l);\r
49 \r
50   fl1.l = MANT (fl1.l);\r
51   fl2.l = MANT (fl2.l);\r
52 \r
53   /* the multiply is done as one 16x16 multiply and two 16x8 multiples */\r
54   result = (fl1.l >> 8) * (fl2.l >> 8);\r
55   result += ((fl1.l & (unsigned long) 0xFF) * (fl2.l >> 8)) >> 8;\r
56   result += ((fl2.l & (unsigned long) 0xFF) * (fl1.l >> 8)) >> 8;\r
57 \r
58   if (0 != (result & SIGNBIT))\r
59     {\r
60       /* round */\r
61       result += 0x80;\r
62       result >>= 8;\r
63     }\r
64   else\r
65     {\r
66       /* round */\r
67       result += 0x40;\r
68       result >>= 7;\r
69       exp--;\r
70     }\r
71 \r
72   result &= ~HIDDEN;\r
73 \r
74   /* pack up and go home */\r
75   if (exp >= 0x100)\r
76     fl1.l = (sign ? SIGNBIT : 0) | 0x7F800000;\r
77   else if (exp < 0)\r
78     fl1.l = 0;\r
79   else\r
80     fl1.l = PACK (sign ? SIGNBIT : 0 , exp, result);\r
81   return (fl1.f);\r
82 }\r
83 \r
84 \r
85 \r
86 \r