diff options
Diffstat (limited to 'arch/mips/math-emu/ieee754dp.c')
-rw-r--r-- | arch/mips/math-emu/ieee754dp.c | 122 |
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 | ||
29 | int ieee754dp_class(ieee754dp x) | 26 | int 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 | ||
36 | int ieee754dp_isnan(ieee754dp x) | 33 | int 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 | ||
41 | int ieee754dp_issnan(ieee754dp x) | 38 | static 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 | ||
48 | ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...) | 45 | union 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 | |||
63 | ieee754dp 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 | ||
90 | ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y) | 64 | static 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 | |||
102 | static 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 | */ |
133 | ieee754dp ieee754dp_format(int sn, int xe, u64 xm) | 95 | union 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); |