File: /usr/src/linux/arch/mips/math-emu/dp_tlong.c
1 /* IEEE754 floating point arithmetic
2 * double precision: common utilities
3 */
4 /*
5 * MIPS floating point support
6 * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved.
7 * http://www.algor.co.uk
8 *
9 * ########################################################################
10 *
11 * This program is free software; you can distribute it and/or modify it
12 * under the terms of the GNU General Public License (Version 2) as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 *
24 * ########################################################################
25 */
26
27
28 #include "ieee754dp.h"
29
30 long long ieee754dp_tlong(ieee754dp x)
31 {
32 COMPXDP;
33
34 CLEARCX;
35
36 EXPLODEXDP;
37
38 switch (xc) {
39 case IEEE754_CLASS_SNAN:
40 case IEEE754_CLASS_QNAN:
41 SETCX(IEEE754_INVALID_OPERATION);
42 return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
43 case IEEE754_CLASS_INF:
44 SETCX(IEEE754_OVERFLOW);
45 return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
46 case IEEE754_CLASS_ZERO:
47 return 0;
48 case IEEE754_CLASS_DNORM: /* much too small */
49 SETCX(IEEE754_UNDERFLOW);
50 return ieee754di_xcpt(0, "dp_tlong", x);
51 case IEEE754_CLASS_NORM:
52 break;
53 }
54 if (xe >= 63) {
55 SETCX(IEEE754_OVERFLOW);
56 return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
57 }
58 if (xe < 0) {
59 if (ieee754_csr.rm == IEEE754_RU) {
60 if (xs) { /* Negative */
61 return 0x0000000000000000LL;
62 } else { /* Positive */
63 return 0x0000000000000001LL;
64 }
65 } else if (ieee754_csr.rm == IEEE754_RD) {
66 if (xs) { /* Negative , return -1 */
67 return 0xffffffffffffffffLL;
68 } else { /* Positive */
69 return 0x0000000000000000LL;
70 }
71 } else {
72 SETCX(IEEE754_UNDERFLOW);
73 return ieee754di_xcpt(0, "dp_tlong", x);
74 }
75 }
76 /* oh gawd */
77 if (xe > DP_MBITS) {
78 xm <<= xe - DP_MBITS;
79 } else if (xe < DP_MBITS) {
80 unsigned long long residue;
81 unsigned long long mask = 0;
82 int i;
83 int round;
84 int sticky;
85 int odd;
86
87 /* compute mask */
88 for (i = 0; i < DP_MBITS - xe; i++) {
89 mask = mask << 1;
90 mask = mask | 0x1;
91 }
92 residue = (xm & mask) << (64 - (DP_MBITS - xe));
93 round =
94 ((0x8000000000000000LL & residue) !=
95 0x0000000000000000LL);
96 sticky =
97 ((0x7fffffffffffffffLL & residue) !=
98 0x0000000000000000LL);
99
100 xm >>= DP_MBITS - xe;
101
102 odd = ((xm & 0x1) != 0x0000000000000000LL);
103
104 /* Do the rounding */
105 if (!round && sticky) {
106 if ((ieee754_csr.rm == IEEE754_RU && !xs)
107 || (ieee754_csr.rm == IEEE754_RD && xs)) {
108 xm++;
109 }
110 } else if (round && !sticky) {
111 if ((ieee754_csr.rm == IEEE754_RU && !xs)
112 || (ieee754_csr.rm == IEEE754_RD && xs)
113 || (ieee754_csr.rm == IEEE754_RN && odd)) {
114 xm++;
115 }
116 } else if (round && sticky) {
117 if ((ieee754_csr.rm == IEEE754_RU && !xs)
118 || (ieee754_csr.rm == IEEE754_RD && xs)
119 || (ieee754_csr.rm == IEEE754_RN)) {
120 xm++;
121 }
122 }
123 }
124 if (xs)
125 return -xm;
126 else
127 return xm;
128 }
129
130
131 unsigned long long ieee754dp_tulong(ieee754dp x)
132 {
133 ieee754dp hb = ieee754dp_1e63();
134
135 /* what if x < 0 ?? */
136 if (ieee754dp_lt(x, hb))
137 return (unsigned long long) ieee754dp_tlong(x);
138
139 return (unsigned long long) ieee754dp_tlong(ieee754dp_sub(x, hb)) |
140 (1ULL << 63);
141 }
142