aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/math-emu/ieee754dp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/math-emu/ieee754dp.c')
-rw-r--r--arch/mips/math-emu/ieee754dp.c122
1 files changed, 42 insertions, 80 deletions
diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c
index 068e56be8de9..fd134675fc2e 100644
--- a/arch/mips/math-emu/ieee754dp.c
+++ b/arch/mips/math-emu/ieee754dp.c
@@ -5,8 +5,6 @@
5 * MIPS floating point support 5 * MIPS floating point support
6 * Copyright (C) 1994-2000 Algorithmics Ltd. 6 * Copyright (C) 1994-2000 Algorithmics Ltd.
7 * 7 *
8 * ########################################################################
9 *
10 * This program is free software; you can distribute it and/or modify it 8 * This program is free software; you can distribute it and/or modify it
11 * under the terms of the GNU General Public License (Version 2) as 9 * under the terms of the GNU General Public License (Version 2) as
12 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
@@ -18,104 +16,68 @@
18 * 16 *
19 * You should have received a copy of the GNU General Public License along 17 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc., 18 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 19 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 * ########################################################################
24 */ 20 */
25 21
22#include <linux/compiler.h>
26 23
27#include "ieee754dp.h" 24#include "ieee754dp.h"
28 25
29int ieee754dp_class(ieee754dp x) 26int ieee754dp_class(union ieee754dp x)
30{ 27{
31 COMPXDP; 28 COMPXDP;
32 EXPLODEXDP; 29 EXPLODEXDP;
33 return xc; 30 return xc;
34} 31}
35 32
36int ieee754dp_isnan(ieee754dp x) 33int ieee754dp_isnan(union ieee754dp x)
37{ 34{
38 return ieee754dp_class(x) >= IEEE754_CLASS_SNAN; 35 return ieee754dp_class(x) >= IEEE754_CLASS_SNAN;
39} 36}
40 37
41int ieee754dp_issnan(ieee754dp x) 38static inline int ieee754dp_issnan(union ieee754dp x)
42{ 39{
43 assert(ieee754dp_isnan(x)); 40 assert(ieee754dp_isnan(x));
44 return ((DPMANT(x) & DP_MBIT(DP_MBITS-1)) == DP_MBIT(DP_MBITS-1)); 41 return ((DPMANT(x) & DP_MBIT(DP_FBITS-1)) == DP_MBIT(DP_FBITS-1));
45} 42}
46 43
47 44
48ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...) 45union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r)
49{
50 struct ieee754xctx ax;
51 if (!TSTX())
52 return r;
53
54 ax.op = op;
55 ax.rt = IEEE754_RT_DP;
56 ax.rv.dp = r;
57 va_start(ax.ap, op);
58 ieee754_xcpt(&ax);
59 va_end(ax.ap);
60 return ax.rv.dp;
61}
62
63ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...)
64{ 46{
65 struct ieee754xctx ax;
66
67 assert(ieee754dp_isnan(r)); 47 assert(ieee754dp_isnan(r));
68 48
69 if (!ieee754dp_issnan(r)) /* QNAN does not cause invalid op !! */ 49 if (!ieee754dp_issnan(r)) /* QNAN does not cause invalid op !! */
70 return r; 50 return r;
71 51
72 if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) { 52 if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) {
73 /* not enabled convert to a quiet NaN */ 53 /* not enabled convert to a quiet NaN */
74 DPMANT(r) &= (~DP_MBIT(DP_MBITS-1)); 54 DPMANT(r) &= (~DP_MBIT(DP_FBITS-1));
75 if (ieee754dp_isnan(r)) 55 if (ieee754dp_isnan(r))
76 return r; 56 return r;
77 else 57 else
78 return ieee754dp_indef(); 58 return ieee754dp_indef();
79 } 59 }
80 60
81 ax.op = op; 61 return r;
82 ax.rt = 0;
83 ax.rv.dp = r;
84 va_start(ax.ap, op);
85 ieee754_xcpt(&ax);
86 va_end(ax.ap);
87 return ax.rv.dp;
88} 62}
89 63
90ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y) 64static u64 ieee754dp_get_rounding(int sn, u64 xm)
91{
92 assert(ieee754dp_isnan(x));
93 assert(ieee754dp_isnan(y));
94
95 if (DPMANT(x) > DPMANT(y))
96 return x;
97 else
98 return y;
99}
100
101
102static u64 get_rounding(int sn, u64 xm)
103{ 65{
104 /* inexact must round of 3 bits 66 /* inexact must round of 3 bits
105 */ 67 */
106 if (xm & (DP_MBIT(3) - 1)) { 68 if (xm & (DP_MBIT(3) - 1)) {
107 switch (ieee754_csr.rm) { 69 switch (ieee754_csr.rm) {
108 case IEEE754_RZ: 70 case FPU_CSR_RZ:
109 break; 71 break;
110 case IEEE754_RN: 72 case FPU_CSR_RN:
111 xm += 0x3 + ((xm >> 3) & 1); 73 xm += 0x3 + ((xm >> 3) & 1);
112 /* xm += (xm&0x8)?0x4:0x3 */ 74 /* xm += (xm&0x8)?0x4:0x3 */
113 break; 75 break;
114 case IEEE754_RU: /* toward +Infinity */ 76 case FPU_CSR_RU: /* toward +Infinity */
115 if (!sn) /* ?? */ 77 if (!sn) /* ?? */
116 xm += 0x8; 78 xm += 0x8;
117 break; 79 break;
118 case IEEE754_RD: /* toward -Infinity */ 80 case FPU_CSR_RD: /* toward -Infinity */
119 if (sn) /* ?? */ 81 if (sn) /* ?? */
120 xm += 0x8; 82 xm += 0x8;
121 break; 83 break;
@@ -130,11 +92,11 @@ static u64 get_rounding(int sn, u64 xm)
130 * xe is an unbiased exponent 92 * xe is an unbiased exponent
131 * xm is 3bit extended precision value. 93 * xm is 3bit extended precision value.
132 */ 94 */
133ieee754dp ieee754dp_format(int sn, int xe, u64 xm) 95union ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
134{ 96{
135 assert(xm); /* we don't gen exact zeros (probably should) */ 97 assert(xm); /* we don't gen exact zeros (probably should) */
136 98
137 assert((xm >> (DP_MBITS + 1 + 3)) == 0); /* no execess */ 99 assert((xm >> (DP_FBITS + 1 + 3)) == 0); /* no execess */
138 assert(xm & (DP_HIDDEN_BIT << 3)); 100 assert(xm & (DP_HIDDEN_BIT << 3));
139 101
140 if (xe < DP_EMIN) { 102 if (xe < DP_EMIN) {
@@ -142,32 +104,32 @@ ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
142 int es = DP_EMIN - xe; 104 int es = DP_EMIN - xe;
143 105
144 if (ieee754_csr.nod) { 106 if (ieee754_csr.nod) {
145 SETCX(IEEE754_UNDERFLOW); 107 ieee754_setcx(IEEE754_UNDERFLOW);
146 SETCX(IEEE754_INEXACT); 108 ieee754_setcx(IEEE754_INEXACT);
147 109
148 switch(ieee754_csr.rm) { 110 switch(ieee754_csr.rm) {
149 case IEEE754_RN: 111 case FPU_CSR_RN:
150 case IEEE754_RZ: 112 case FPU_CSR_RZ:
151 return ieee754dp_zero(sn); 113 return ieee754dp_zero(sn);
152 case IEEE754_RU: /* toward +Infinity */ 114 case FPU_CSR_RU: /* toward +Infinity */
153 if(sn == 0) 115 if (sn == 0)
154 return ieee754dp_min(0); 116 return ieee754dp_min(0);
155 else 117 else
156 return ieee754dp_zero(1); 118 return ieee754dp_zero(1);
157 case IEEE754_RD: /* toward -Infinity */ 119 case FPU_CSR_RD: /* toward -Infinity */
158 if(sn == 0) 120 if (sn == 0)
159 return ieee754dp_zero(0); 121 return ieee754dp_zero(0);
160 else 122 else
161 return ieee754dp_min(1); 123 return ieee754dp_min(1);
162 } 124 }
163 } 125 }
164 126
165 if (xe == DP_EMIN - 1 127 if (xe == DP_EMIN - 1 &&
166 && get_rounding(sn, xm) >> (DP_MBITS + 1 + 3)) 128 ieee754dp_get_rounding(sn, xm) >> (DP_FBITS + 1 + 3))
167 { 129 {
168 /* Not tiny after rounding */ 130 /* Not tiny after rounding */
169 SETCX(IEEE754_INEXACT); 131 ieee754_setcx(IEEE754_INEXACT);
170 xm = get_rounding(sn, xm); 132 xm = ieee754dp_get_rounding(sn, xm);
171 xm >>= 1; 133 xm >>= 1;
172 /* Clear grs bits */ 134 /* Clear grs bits */
173 xm &= ~(DP_MBIT(3) - 1); 135 xm &= ~(DP_MBIT(3) - 1);
@@ -183,17 +145,17 @@ ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
183 } 145 }
184 } 146 }
185 if (xm & (DP_MBIT(3) - 1)) { 147 if (xm & (DP_MBIT(3) - 1)) {
186 SETCX(IEEE754_INEXACT); 148 ieee754_setcx(IEEE754_INEXACT);
187 if ((xm & (DP_HIDDEN_BIT << 3)) == 0) { 149 if ((xm & (DP_HIDDEN_BIT << 3)) == 0) {
188 SETCX(IEEE754_UNDERFLOW); 150 ieee754_setcx(IEEE754_UNDERFLOW);
189 } 151 }
190 152
191 /* inexact must round of 3 bits 153 /* inexact must round of 3 bits
192 */ 154 */
193 xm = get_rounding(sn, xm); 155 xm = ieee754dp_get_rounding(sn, xm);
194 /* adjust exponent for rounding add overflowing 156 /* adjust exponent for rounding add overflowing
195 */ 157 */
196 if (xm >> (DP_MBITS + 3 + 1)) { 158 if (xm >> (DP_FBITS + 3 + 1)) {
197 /* add causes mantissa overflow */ 159 /* add causes mantissa overflow */
198 xm >>= 1; 160 xm >>= 1;
199 xe++; 161 xe++;
@@ -202,24 +164,24 @@ ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
202 /* strip grs bits */ 164 /* strip grs bits */
203 xm >>= 3; 165 xm >>= 3;
204 166
205 assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */ 167 assert((xm >> (DP_FBITS + 1)) == 0); /* no execess */
206 assert(xe >= DP_EMIN); 168 assert(xe >= DP_EMIN);
207 169
208 if (xe > DP_EMAX) { 170 if (xe > DP_EMAX) {
209 SETCX(IEEE754_OVERFLOW); 171 ieee754_setcx(IEEE754_OVERFLOW);
210 SETCX(IEEE754_INEXACT); 172 ieee754_setcx(IEEE754_INEXACT);
211 /* -O can be table indexed by (rm,sn) */ 173 /* -O can be table indexed by (rm,sn) */
212 switch (ieee754_csr.rm) { 174 switch (ieee754_csr.rm) {
213 case IEEE754_RN: 175 case FPU_CSR_RN:
214 return ieee754dp_inf(sn); 176 return ieee754dp_inf(sn);
215 case IEEE754_RZ: 177 case FPU_CSR_RZ:
216 return ieee754dp_max(sn); 178 return ieee754dp_max(sn);
217 case IEEE754_RU: /* toward +Infinity */ 179 case FPU_CSR_RU: /* toward +Infinity */
218 if (sn == 0) 180 if (sn == 0)
219 return ieee754dp_inf(0); 181 return ieee754dp_inf(0);
220 else 182 else
221 return ieee754dp_max(1); 183 return ieee754dp_max(1);
222 case IEEE754_RD: /* toward -Infinity */ 184 case FPU_CSR_RD: /* toward -Infinity */
223 if (sn == 0) 185 if (sn == 0)
224 return ieee754dp_max(0); 186 return ieee754dp_max(0);
225 else 187 else
@@ -232,10 +194,10 @@ ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
232 /* we underflow (tiny/zero) */ 194 /* we underflow (tiny/zero) */
233 assert(xe == DP_EMIN); 195 assert(xe == DP_EMIN);
234 if (ieee754_csr.mx & IEEE754_UNDERFLOW) 196 if (ieee754_csr.mx & IEEE754_UNDERFLOW)
235 SETCX(IEEE754_UNDERFLOW); 197 ieee754_setcx(IEEE754_UNDERFLOW);
236 return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm); 198 return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm);
237 } else { 199 } else {
238 assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */ 200 assert((xm >> (DP_FBITS + 1)) == 0); /* no execess */
239 assert(xm & DP_HIDDEN_BIT); 201 assert(xm & DP_HIDDEN_BIT);
240 202
241 return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); 203 return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);