diff options
Diffstat (limited to 'arch/mips/math-emu/ieee754sp.c')
-rw-r--r-- | arch/mips/math-emu/ieee754sp.c | 126 |
1 files changed, 43 insertions, 83 deletions
diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index 15d1e36cfe64..d348efe91445 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.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,105 +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 "ieee754sp.h" | 24 | #include "ieee754sp.h" |
28 | 25 | ||
29 | int ieee754sp_class(ieee754sp x) | 26 | int ieee754sp_class(union ieee754sp x) |
30 | { | 27 | { |
31 | COMPXSP; | 28 | COMPXSP; |
32 | EXPLODEXSP; | 29 | EXPLODEXSP; |
33 | return xc; | 30 | return xc; |
34 | } | 31 | } |
35 | 32 | ||
36 | int ieee754sp_isnan(ieee754sp x) | 33 | int ieee754sp_isnan(union ieee754sp x) |
37 | { | 34 | { |
38 | return ieee754sp_class(x) >= IEEE754_CLASS_SNAN; | 35 | return ieee754sp_class(x) >= IEEE754_CLASS_SNAN; |
39 | } | 36 | } |
40 | 37 | ||
41 | int ieee754sp_issnan(ieee754sp x) | 38 | static inline int ieee754sp_issnan(union ieee754sp x) |
42 | { | 39 | { |
43 | assert(ieee754sp_isnan(x)); | 40 | assert(ieee754sp_isnan(x)); |
44 | return (SPMANT(x) & SP_MBIT(SP_MBITS-1)); | 41 | return (SPMANT(x) & SP_MBIT(SP_FBITS-1)); |
45 | } | 42 | } |
46 | 43 | ||
47 | 44 | ||
48 | ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...) | 45 | union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r) |
49 | { | ||
50 | struct ieee754xctx ax; | ||
51 | |||
52 | if (!TSTX()) | ||
53 | return r; | ||
54 | |||
55 | ax.op = op; | ||
56 | ax.rt = IEEE754_RT_SP; | ||
57 | ax.rv.sp = r; | ||
58 | va_start(ax.ap, op); | ||
59 | ieee754_xcpt(&ax); | ||
60 | va_end(ax.ap); | ||
61 | return ax.rv.sp; | ||
62 | } | ||
63 | |||
64 | ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...) | ||
65 | { | 46 | { |
66 | struct ieee754xctx ax; | ||
67 | |||
68 | assert(ieee754sp_isnan(r)); | 47 | assert(ieee754sp_isnan(r)); |
69 | 48 | ||
70 | if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */ | 49 | if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */ |
71 | return r; | 50 | return r; |
72 | 51 | ||
73 | if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) { | 52 | if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) { |
74 | /* not enabled convert to a quiet NaN */ | 53 | /* not enabled convert to a quiet NaN */ |
75 | SPMANT(r) &= (~SP_MBIT(SP_MBITS-1)); | 54 | SPMANT(r) &= (~SP_MBIT(SP_FBITS-1)); |
76 | if (ieee754sp_isnan(r)) | 55 | if (ieee754sp_isnan(r)) |
77 | return r; | 56 | return r; |
78 | else | 57 | else |
79 | return ieee754sp_indef(); | 58 | return ieee754sp_indef(); |
80 | } | 59 | } |
81 | 60 | ||
82 | ax.op = op; | 61 | return r; |
83 | ax.rt = 0; | ||
84 | ax.rv.sp = r; | ||
85 | va_start(ax.ap, op); | ||
86 | ieee754_xcpt(&ax); | ||
87 | va_end(ax.ap); | ||
88 | return ax.rv.sp; | ||
89 | } | ||
90 | |||
91 | ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y) | ||
92 | { | ||
93 | assert(ieee754sp_isnan(x)); | ||
94 | assert(ieee754sp_isnan(y)); | ||
95 | |||
96 | if (SPMANT(x) > SPMANT(y)) | ||
97 | return x; | ||
98 | else | ||
99 | return y; | ||
100 | } | 62 | } |
101 | 63 | ||
102 | 64 | static unsigned ieee754sp_get_rounding(int sn, unsigned xm) | |
103 | static unsigned get_rounding(int sn, unsigned xm) | ||
104 | { | 65 | { |
105 | /* inexact must round of 3 bits | 66 | /* inexact must round of 3 bits |
106 | */ | 67 | */ |
107 | if (xm & (SP_MBIT(3) - 1)) { | 68 | if (xm & (SP_MBIT(3) - 1)) { |
108 | switch (ieee754_csr.rm) { | 69 | switch (ieee754_csr.rm) { |
109 | case IEEE754_RZ: | 70 | case FPU_CSR_RZ: |
110 | break; | 71 | break; |
111 | case IEEE754_RN: | 72 | case FPU_CSR_RN: |
112 | xm += 0x3 + ((xm >> 3) & 1); | 73 | xm += 0x3 + ((xm >> 3) & 1); |
113 | /* xm += (xm&0x8)?0x4:0x3 */ | 74 | /* xm += (xm&0x8)?0x4:0x3 */ |
114 | break; | 75 | break; |
115 | case IEEE754_RU: /* toward +Infinity */ | 76 | case FPU_CSR_RU: /* toward +Infinity */ |
116 | if (!sn) /* ?? */ | 77 | if (!sn) /* ?? */ |
117 | xm += 0x8; | 78 | xm += 0x8; |
118 | break; | 79 | break; |
119 | case IEEE754_RD: /* toward -Infinity */ | 80 | case FPU_CSR_RD: /* toward -Infinity */ |
120 | if (sn) /* ?? */ | 81 | if (sn) /* ?? */ |
121 | xm += 0x8; | 82 | xm += 0x8; |
122 | break; | 83 | break; |
@@ -131,11 +92,11 @@ static unsigned get_rounding(int sn, unsigned xm) | |||
131 | * xe is an unbiased exponent | 92 | * xe is an unbiased exponent |
132 | * xm is 3bit extended precision value. | 93 | * xm is 3bit extended precision value. |
133 | */ | 94 | */ |
134 | ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) | 95 | union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) |
135 | { | 96 | { |
136 | assert(xm); /* we don't gen exact zeros (probably should) */ | 97 | assert(xm); /* we don't gen exact zeros (probably should) */ |
137 | 98 | ||
138 | assert((xm >> (SP_MBITS + 1 + 3)) == 0); /* no execess */ | 99 | assert((xm >> (SP_FBITS + 1 + 3)) == 0); /* no execess */ |
139 | assert(xm & (SP_HIDDEN_BIT << 3)); | 100 | assert(xm & (SP_HIDDEN_BIT << 3)); |
140 | 101 | ||
141 | if (xe < SP_EMIN) { | 102 | if (xe < SP_EMIN) { |
@@ -143,38 +104,37 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) | |||
143 | int es = SP_EMIN - xe; | 104 | int es = SP_EMIN - xe; |
144 | 105 | ||
145 | if (ieee754_csr.nod) { | 106 | if (ieee754_csr.nod) { |
146 | SETCX(IEEE754_UNDERFLOW); | 107 | ieee754_setcx(IEEE754_UNDERFLOW); |
147 | SETCX(IEEE754_INEXACT); | 108 | ieee754_setcx(IEEE754_INEXACT); |
148 | 109 | ||
149 | switch(ieee754_csr.rm) { | 110 | switch(ieee754_csr.rm) { |
150 | case IEEE754_RN: | 111 | case FPU_CSR_RN: |
151 | case IEEE754_RZ: | 112 | case FPU_CSR_RZ: |
152 | return ieee754sp_zero(sn); | 113 | return ieee754sp_zero(sn); |
153 | case IEEE754_RU: /* toward +Infinity */ | 114 | case FPU_CSR_RU: /* toward +Infinity */ |
154 | if(sn == 0) | 115 | if (sn == 0) |
155 | return ieee754sp_min(0); | 116 | return ieee754sp_min(0); |
156 | else | 117 | else |
157 | return ieee754sp_zero(1); | 118 | return ieee754sp_zero(1); |
158 | case IEEE754_RD: /* toward -Infinity */ | 119 | case FPU_CSR_RD: /* toward -Infinity */ |
159 | if(sn == 0) | 120 | if (sn == 0) |
160 | return ieee754sp_zero(0); | 121 | return ieee754sp_zero(0); |
161 | else | 122 | else |
162 | return ieee754sp_min(1); | 123 | return ieee754sp_min(1); |
163 | } | 124 | } |
164 | } | 125 | } |
165 | 126 | ||
166 | if (xe == SP_EMIN - 1 | 127 | if (xe == SP_EMIN - 1 && |
167 | && get_rounding(sn, xm) >> (SP_MBITS + 1 + 3)) | 128 | ieee754sp_get_rounding(sn, xm) >> (SP_FBITS + 1 + 3)) |
168 | { | 129 | { |
169 | /* Not tiny after rounding */ | 130 | /* Not tiny after rounding */ |
170 | SETCX(IEEE754_INEXACT); | 131 | ieee754_setcx(IEEE754_INEXACT); |
171 | xm = get_rounding(sn, xm); | 132 | xm = ieee754sp_get_rounding(sn, xm); |
172 | xm >>= 1; | 133 | xm >>= 1; |
173 | /* Clear grs bits */ | 134 | /* Clear grs bits */ |
174 | xm &= ~(SP_MBIT(3) - 1); | 135 | xm &= ~(SP_MBIT(3) - 1); |
175 | xe++; | 136 | xe++; |
176 | } | 137 | } else { |
177 | else { | ||
178 | /* sticky right shift es bits | 138 | /* sticky right shift es bits |
179 | */ | 139 | */ |
180 | SPXSRSXn(es); | 140 | SPXSRSXn(es); |
@@ -183,17 +143,17 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) | |||
183 | } | 143 | } |
184 | } | 144 | } |
185 | if (xm & (SP_MBIT(3) - 1)) { | 145 | if (xm & (SP_MBIT(3) - 1)) { |
186 | SETCX(IEEE754_INEXACT); | 146 | ieee754_setcx(IEEE754_INEXACT); |
187 | if ((xm & (SP_HIDDEN_BIT << 3)) == 0) { | 147 | if ((xm & (SP_HIDDEN_BIT << 3)) == 0) { |
188 | SETCX(IEEE754_UNDERFLOW); | 148 | ieee754_setcx(IEEE754_UNDERFLOW); |
189 | } | 149 | } |
190 | 150 | ||
191 | /* inexact must round of 3 bits | 151 | /* inexact must round of 3 bits |
192 | */ | 152 | */ |
193 | xm = get_rounding(sn, xm); | 153 | xm = ieee754sp_get_rounding(sn, xm); |
194 | /* adjust exponent for rounding add overflowing | 154 | /* adjust exponent for rounding add overflowing |
195 | */ | 155 | */ |
196 | if (xm >> (SP_MBITS + 1 + 3)) { | 156 | if (xm >> (SP_FBITS + 1 + 3)) { |
197 | /* add causes mantissa overflow */ | 157 | /* add causes mantissa overflow */ |
198 | xm >>= 1; | 158 | xm >>= 1; |
199 | xe++; | 159 | xe++; |
@@ -202,24 +162,24 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) | |||
202 | /* strip grs bits */ | 162 | /* strip grs bits */ |
203 | xm >>= 3; | 163 | xm >>= 3; |
204 | 164 | ||
205 | assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */ | 165 | assert((xm >> (SP_FBITS + 1)) == 0); /* no execess */ |
206 | assert(xe >= SP_EMIN); | 166 | assert(xe >= SP_EMIN); |
207 | 167 | ||
208 | if (xe > SP_EMAX) { | 168 | if (xe > SP_EMAX) { |
209 | SETCX(IEEE754_OVERFLOW); | 169 | ieee754_setcx(IEEE754_OVERFLOW); |
210 | SETCX(IEEE754_INEXACT); | 170 | ieee754_setcx(IEEE754_INEXACT); |
211 | /* -O can be table indexed by (rm,sn) */ | 171 | /* -O can be table indexed by (rm,sn) */ |
212 | switch (ieee754_csr.rm) { | 172 | switch (ieee754_csr.rm) { |
213 | case IEEE754_RN: | 173 | case FPU_CSR_RN: |
214 | return ieee754sp_inf(sn); | 174 | return ieee754sp_inf(sn); |
215 | case IEEE754_RZ: | 175 | case FPU_CSR_RZ: |
216 | return ieee754sp_max(sn); | 176 | return ieee754sp_max(sn); |
217 | case IEEE754_RU: /* toward +Infinity */ | 177 | case FPU_CSR_RU: /* toward +Infinity */ |
218 | if (sn == 0) | 178 | if (sn == 0) |
219 | return ieee754sp_inf(0); | 179 | return ieee754sp_inf(0); |
220 | else | 180 | else |
221 | return ieee754sp_max(1); | 181 | return ieee754sp_max(1); |
222 | case IEEE754_RD: /* toward -Infinity */ | 182 | case FPU_CSR_RD: /* toward -Infinity */ |
223 | if (sn == 0) | 183 | if (sn == 0) |
224 | return ieee754sp_max(0); | 184 | return ieee754sp_max(0); |
225 | else | 185 | else |
@@ -232,10 +192,10 @@ ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) | |||
232 | /* we underflow (tiny/zero) */ | 192 | /* we underflow (tiny/zero) */ |
233 | assert(xe == SP_EMIN); | 193 | assert(xe == SP_EMIN); |
234 | if (ieee754_csr.mx & IEEE754_UNDERFLOW) | 194 | if (ieee754_csr.mx & IEEE754_UNDERFLOW) |
235 | SETCX(IEEE754_UNDERFLOW); | 195 | ieee754_setcx(IEEE754_UNDERFLOW); |
236 | return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm); | 196 | return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm); |
237 | } else { | 197 | } else { |
238 | assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */ | 198 | assert((xm >> (SP_FBITS + 1)) == 0); /* no execess */ |
239 | assert(xm & SP_HIDDEN_BIT); | 199 | assert(xm & SP_HIDDEN_BIT); |
240 | 200 | ||
241 | return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT); | 201 | return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT); |