floatformat.c revision 1.3 1 1.1 skrll /* IEEE floating point support routines, for GDB, the GNU Debugger.
2 1.1 skrll Copyright 1991, 1994, 1999, 2000, 2003, 2005, 2006
3 1.1 skrll Free Software Foundation, Inc.
4 1.1 skrll
5 1.1 skrll This file is part of GDB.
6 1.1 skrll
7 1.1 skrll This program is free software; you can redistribute it and/or modify
8 1.1 skrll it under the terms of the GNU General Public License as published by
9 1.1 skrll the Free Software Foundation; either version 2 of the License, or
10 1.1 skrll (at your option) any later version.
11 1.1 skrll
12 1.1 skrll This program is distributed in the hope that it will be useful,
13 1.1 skrll but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 skrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 skrll GNU General Public License for more details.
16 1.1 skrll
17 1.1 skrll You should have received a copy of the GNU General Public License
18 1.1 skrll along with this program; if not, write to the Free Software
19 1.1 skrll Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20 1.1 skrll
21 1.1 skrll /* This is needed to pick up the NAN macro on some systems. */
22 1.1 skrll #define _GNU_SOURCE
23 1.1 skrll
24 1.1 skrll #ifdef HAVE_CONFIG_H
25 1.1 skrll #include "config.h"
26 1.1 skrll #endif
27 1.1 skrll
28 1.1 skrll #include <math.h>
29 1.1 skrll
30 1.1 skrll #ifdef HAVE_STRING_H
31 1.1 skrll #include <string.h>
32 1.1 skrll #endif
33 1.1 skrll
34 1.1 skrll /* On some platforms, <float.h> provides DBL_QNAN. */
35 1.1 skrll #ifdef STDC_HEADERS
36 1.1 skrll #include <float.h>
37 1.1 skrll #endif
38 1.1 skrll
39 1.1 skrll #include "ansidecl.h"
40 1.1 skrll #include "libiberty.h"
41 1.1 skrll #include "floatformat.h"
42 1.1 skrll
43 1.1 skrll #ifndef INFINITY
44 1.1 skrll #ifdef HUGE_VAL
45 1.1 skrll #define INFINITY HUGE_VAL
46 1.1 skrll #else
47 1.1 skrll #define INFINITY (1.0 / 0.0)
48 1.1 skrll #endif
49 1.1 skrll #endif
50 1.1 skrll
51 1.1 skrll #ifndef NAN
52 1.1 skrll #ifdef DBL_QNAN
53 1.1 skrll #define NAN DBL_QNAN
54 1.1 skrll #else
55 1.1 skrll #define NAN (0.0 / 0.0)
56 1.1 skrll #endif
57 1.1 skrll #endif
58 1.1 skrll
59 1.1 skrll static int mant_bits_set (const struct floatformat *, const unsigned char *);
60 1.1 skrll static unsigned long get_field (const unsigned char *,
61 1.1 skrll enum floatformat_byteorders,
62 1.1 skrll unsigned int,
63 1.1 skrll unsigned int,
64 1.1 skrll unsigned int);
65 1.1 skrll static int floatformat_always_valid (const struct floatformat *fmt,
66 1.1 skrll const void *from);
67 1.1 skrll
68 1.1 skrll static int
69 1.1 skrll floatformat_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED,
70 1.1 skrll const void *from ATTRIBUTE_UNUSED)
71 1.1 skrll {
72 1.1 skrll return 1;
73 1.1 skrll }
74 1.1 skrll
75 1.1 skrll /* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
76 1.1 skrll going to bother with trying to muck around with whether it is defined in
77 1.1 skrll a system header, what we do if not, etc. */
78 1.1 skrll #define FLOATFORMAT_CHAR_BIT 8
79 1.1 skrll
80 1.3 christos /* floatformats for IEEE half, single and double, big and little endian. */
81 1.3 christos const struct floatformat floatformat_ieee_half_big =
82 1.3 christos {
83 1.3 christos floatformat_big, 16, 0, 1, 5, 15, 31, 6, 10,
84 1.3 christos floatformat_intbit_no,
85 1.3 christos "floatformat_ieee_half_big",
86 1.3 christos floatformat_always_valid,
87 1.3 christos NULL
88 1.3 christos };
89 1.3 christos const struct floatformat floatformat_ieee_half_little =
90 1.3 christos {
91 1.3 christos floatformat_little, 16, 0, 1, 5, 15, 31, 6, 10,
92 1.3 christos floatformat_intbit_no,
93 1.3 christos "floatformat_ieee_half_little",
94 1.3 christos floatformat_always_valid,
95 1.3 christos NULL
96 1.3 christos };
97 1.1 skrll const struct floatformat floatformat_ieee_single_big =
98 1.1 skrll {
99 1.1 skrll floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23,
100 1.1 skrll floatformat_intbit_no,
101 1.1 skrll "floatformat_ieee_single_big",
102 1.1 skrll floatformat_always_valid,
103 1.1 skrll NULL
104 1.1 skrll };
105 1.1 skrll const struct floatformat floatformat_ieee_single_little =
106 1.1 skrll {
107 1.1 skrll floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23,
108 1.1 skrll floatformat_intbit_no,
109 1.1 skrll "floatformat_ieee_single_little",
110 1.1 skrll floatformat_always_valid,
111 1.1 skrll NULL
112 1.1 skrll };
113 1.1 skrll const struct floatformat floatformat_ieee_double_big =
114 1.1 skrll {
115 1.1 skrll floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52,
116 1.1 skrll floatformat_intbit_no,
117 1.1 skrll "floatformat_ieee_double_big",
118 1.1 skrll floatformat_always_valid,
119 1.1 skrll NULL
120 1.1 skrll };
121 1.1 skrll const struct floatformat floatformat_ieee_double_little =
122 1.1 skrll {
123 1.1 skrll floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52,
124 1.1 skrll floatformat_intbit_no,
125 1.1 skrll "floatformat_ieee_double_little",
126 1.1 skrll floatformat_always_valid,
127 1.1 skrll NULL
128 1.1 skrll };
129 1.1 skrll
130 1.1 skrll /* floatformat for IEEE double, little endian byte order, with big endian word
131 1.1 skrll ordering, as on the ARM. */
132 1.1 skrll
133 1.1 skrll const struct floatformat floatformat_ieee_double_littlebyte_bigword =
134 1.1 skrll {
135 1.1 skrll floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52,
136 1.1 skrll floatformat_intbit_no,
137 1.1 skrll "floatformat_ieee_double_littlebyte_bigword",
138 1.1 skrll floatformat_always_valid,
139 1.1 skrll NULL
140 1.1 skrll };
141 1.1 skrll
142 1.1 skrll /* floatformat for VAX. Not quite IEEE, but close enough. */
143 1.1 skrll
144 1.1 skrll const struct floatformat floatformat_vax_f =
145 1.1 skrll {
146 1.1 skrll floatformat_vax, 32, 0, 1, 8, 129, 0, 9, 23,
147 1.1 skrll floatformat_intbit_no,
148 1.1 skrll "floatformat_vax_f",
149 1.1 skrll floatformat_always_valid,
150 1.1 skrll NULL
151 1.1 skrll };
152 1.1 skrll const struct floatformat floatformat_vax_d =
153 1.1 skrll {
154 1.1 skrll floatformat_vax, 64, 0, 1, 8, 129, 0, 9, 55,
155 1.1 skrll floatformat_intbit_no,
156 1.1 skrll "floatformat_vax_d",
157 1.1 skrll floatformat_always_valid,
158 1.1 skrll NULL
159 1.1 skrll };
160 1.1 skrll const struct floatformat floatformat_vax_g =
161 1.1 skrll {
162 1.1 skrll floatformat_vax, 64, 0, 1, 11, 1025, 0, 12, 52,
163 1.1 skrll floatformat_intbit_no,
164 1.1 skrll "floatformat_vax_g",
165 1.1 skrll floatformat_always_valid,
166 1.1 skrll NULL
167 1.1 skrll };
168 1.1 skrll
169 1.1 skrll static int floatformat_i387_ext_is_valid (const struct floatformat *fmt,
170 1.1 skrll const void *from);
171 1.1 skrll
172 1.1 skrll static int
173 1.1 skrll floatformat_i387_ext_is_valid (const struct floatformat *fmt, const void *from)
174 1.1 skrll {
175 1.1 skrll /* In the i387 double-extended format, if the exponent is all ones,
176 1.1 skrll then the integer bit must be set. If the exponent is neither 0
177 1.1 skrll nor ~0, the intbit must also be set. Only if the exponent is
178 1.1 skrll zero can it be zero, and then it must be zero. */
179 1.1 skrll unsigned long exponent, int_bit;
180 1.1 skrll const unsigned char *ufrom = (const unsigned char *) from;
181 1.1 skrll
182 1.1 skrll exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
183 1.1 skrll fmt->exp_start, fmt->exp_len);
184 1.1 skrll int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize,
185 1.1 skrll fmt->man_start, 1);
186 1.1 skrll
187 1.1 skrll if ((exponent == 0) != (int_bit == 0))
188 1.1 skrll return 0;
189 1.1 skrll else
190 1.1 skrll return 1;
191 1.1 skrll }
192 1.1 skrll
193 1.1 skrll const struct floatformat floatformat_i387_ext =
194 1.1 skrll {
195 1.1 skrll floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
196 1.1 skrll floatformat_intbit_yes,
197 1.1 skrll "floatformat_i387_ext",
198 1.1 skrll floatformat_i387_ext_is_valid,
199 1.1 skrll NULL
200 1.1 skrll };
201 1.1 skrll const struct floatformat floatformat_m68881_ext =
202 1.1 skrll {
203 1.1 skrll /* Note that the bits from 16 to 31 are unused. */
204 1.1 skrll floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
205 1.1 skrll floatformat_intbit_yes,
206 1.1 skrll "floatformat_m68881_ext",
207 1.1 skrll floatformat_always_valid,
208 1.1 skrll NULL
209 1.1 skrll };
210 1.1 skrll const struct floatformat floatformat_i960_ext =
211 1.1 skrll {
212 1.1 skrll /* Note that the bits from 0 to 15 are unused. */
213 1.1 skrll floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
214 1.1 skrll floatformat_intbit_yes,
215 1.1 skrll "floatformat_i960_ext",
216 1.1 skrll floatformat_always_valid,
217 1.1 skrll NULL
218 1.1 skrll };
219 1.1 skrll const struct floatformat floatformat_m88110_ext =
220 1.1 skrll {
221 1.1 skrll floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
222 1.1 skrll floatformat_intbit_yes,
223 1.1 skrll "floatformat_m88110_ext",
224 1.1 skrll floatformat_always_valid,
225 1.1 skrll NULL
226 1.1 skrll };
227 1.1 skrll const struct floatformat floatformat_m88110_harris_ext =
228 1.1 skrll {
229 1.1 skrll /* Harris uses raw format 128 bytes long, but the number is just an ieee
230 1.1 skrll double, and the last 64 bits are wasted. */
231 1.1 skrll floatformat_big,128, 0, 1, 11, 0x3ff, 0x7ff, 12, 52,
232 1.1 skrll floatformat_intbit_no,
233 1.1 skrll "floatformat_m88110_ext_harris",
234 1.1 skrll floatformat_always_valid,
235 1.1 skrll NULL
236 1.1 skrll };
237 1.1 skrll const struct floatformat floatformat_arm_ext_big =
238 1.1 skrll {
239 1.1 skrll /* Bits 1 to 16 are unused. */
240 1.1 skrll floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
241 1.1 skrll floatformat_intbit_yes,
242 1.1 skrll "floatformat_arm_ext_big",
243 1.1 skrll floatformat_always_valid,
244 1.1 skrll NULL
245 1.1 skrll };
246 1.1 skrll const struct floatformat floatformat_arm_ext_littlebyte_bigword =
247 1.1 skrll {
248 1.1 skrll /* Bits 1 to 16 are unused. */
249 1.1 skrll floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
250 1.1 skrll floatformat_intbit_yes,
251 1.1 skrll "floatformat_arm_ext_littlebyte_bigword",
252 1.1 skrll floatformat_always_valid,
253 1.1 skrll NULL
254 1.1 skrll };
255 1.1 skrll const struct floatformat floatformat_ia64_spill_big =
256 1.1 skrll {
257 1.1 skrll floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
258 1.1 skrll floatformat_intbit_yes,
259 1.1 skrll "floatformat_ia64_spill_big",
260 1.1 skrll floatformat_always_valid,
261 1.1 skrll NULL
262 1.1 skrll };
263 1.1 skrll const struct floatformat floatformat_ia64_spill_little =
264 1.1 skrll {
265 1.1 skrll floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
266 1.1 skrll floatformat_intbit_yes,
267 1.1 skrll "floatformat_ia64_spill_little",
268 1.1 skrll floatformat_always_valid,
269 1.1 skrll NULL
270 1.1 skrll };
271 1.1 skrll const struct floatformat floatformat_ia64_quad_big =
272 1.1 skrll {
273 1.1 skrll floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
274 1.1 skrll floatformat_intbit_no,
275 1.1 skrll "floatformat_ia64_quad_big",
276 1.1 skrll floatformat_always_valid,
277 1.1 skrll NULL
278 1.1 skrll };
279 1.1 skrll const struct floatformat floatformat_ia64_quad_little =
280 1.1 skrll {
281 1.1 skrll floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
282 1.1 skrll floatformat_intbit_no,
283 1.1 skrll "floatformat_ia64_quad_little",
284 1.1 skrll floatformat_always_valid,
285 1.1 skrll NULL
286 1.1 skrll };
287 1.1 skrll
288 1.1 skrll static int
289 1.1 skrll floatformat_ibm_long_double_is_valid (const struct floatformat *fmt,
290 1.1 skrll const void *from)
291 1.1 skrll {
292 1.1 skrll const unsigned char *ufrom = (const unsigned char *) from;
293 1.1 skrll const struct floatformat *hfmt = fmt->split_half;
294 1.1 skrll long top_exp, bot_exp;
295 1.1 skrll int top_nan = 0;
296 1.1 skrll
297 1.1 skrll top_exp = get_field (ufrom, hfmt->byteorder, hfmt->totalsize,
298 1.1 skrll hfmt->exp_start, hfmt->exp_len);
299 1.1 skrll bot_exp = get_field (ufrom + 8, hfmt->byteorder, hfmt->totalsize,
300 1.1 skrll hfmt->exp_start, hfmt->exp_len);
301 1.1 skrll
302 1.1 skrll if ((unsigned long) top_exp == hfmt->exp_nan)
303 1.1 skrll top_nan = mant_bits_set (hfmt, ufrom);
304 1.1 skrll
305 1.1 skrll /* A NaN is valid with any low part. */
306 1.1 skrll if (top_nan)
307 1.1 skrll return 1;
308 1.1 skrll
309 1.1 skrll /* An infinity, zero or denormal requires low part 0 (positive or
310 1.1 skrll negative). */
311 1.1 skrll if ((unsigned long) top_exp == hfmt->exp_nan || top_exp == 0)
312 1.1 skrll {
313 1.1 skrll if (bot_exp != 0)
314 1.1 skrll return 0;
315 1.1 skrll
316 1.1 skrll return !mant_bits_set (hfmt, ufrom + 8);
317 1.1 skrll }
318 1.1 skrll
319 1.1 skrll /* The top part is now a finite normal value. The long double value
320 1.1 skrll is the sum of the two parts, and the top part must equal the
321 1.1 skrll result of rounding the long double value to nearest double. Thus
322 1.1 skrll the bottom part must be <= 0.5ulp of the top part in absolute
323 1.1 skrll value, and if it is < 0.5ulp then the long double is definitely
324 1.1 skrll valid. */
325 1.1 skrll if (bot_exp < top_exp - 53)
326 1.1 skrll return 1;
327 1.1 skrll if (bot_exp > top_exp - 53 && bot_exp != 0)
328 1.1 skrll return 0;
329 1.1 skrll if (bot_exp == 0)
330 1.1 skrll {
331 1.1 skrll /* The bottom part is 0 or denormal. Determine which, and if
332 1.1 skrll denormal the first two set bits. */
333 1.1 skrll int first_bit = -1, second_bit = -1, cur_bit;
334 1.1 skrll for (cur_bit = 0; (unsigned int) cur_bit < hfmt->man_len; cur_bit++)
335 1.1 skrll if (get_field (ufrom + 8, hfmt->byteorder, hfmt->totalsize,
336 1.1 skrll hfmt->man_start + cur_bit, 1))
337 1.1 skrll {
338 1.1 skrll if (first_bit == -1)
339 1.1 skrll first_bit = cur_bit;
340 1.1 skrll else
341 1.1 skrll {
342 1.1 skrll second_bit = cur_bit;
343 1.1 skrll break;
344 1.1 skrll }
345 1.1 skrll }
346 1.1 skrll /* Bottom part 0 is OK. */
347 1.1 skrll if (first_bit == -1)
348 1.1 skrll return 1;
349 1.1 skrll /* The real exponent of the bottom part is -first_bit. */
350 1.1 skrll if (-first_bit < top_exp - 53)
351 1.1 skrll return 1;
352 1.1 skrll if (-first_bit > top_exp - 53)
353 1.1 skrll return 0;
354 1.1 skrll /* The bottom part is at least 0.5ulp of the top part. For this
355 1.1 skrll to be OK, the bottom part must be exactly 0.5ulp (i.e. no
356 1.1 skrll more bits set) and the top part must have last bit 0. */
357 1.1 skrll if (second_bit != -1)
358 1.1 skrll return 0;
359 1.1 skrll return !get_field (ufrom, hfmt->byteorder, hfmt->totalsize,
360 1.1 skrll hfmt->man_start + hfmt->man_len - 1, 1);
361 1.1 skrll }
362 1.1 skrll else
363 1.1 skrll {
364 1.1 skrll /* The bottom part is at least 0.5ulp of the top part. For this
365 1.1 skrll to be OK, it must be exactly 0.5ulp (i.e. no explicit bits
366 1.1 skrll set) and the top part must have last bit 0. */
367 1.1 skrll if (get_field (ufrom, hfmt->byteorder, hfmt->totalsize,
368 1.1 skrll hfmt->man_start + hfmt->man_len - 1, 1))
369 1.1 skrll return 0;
370 1.1 skrll return !mant_bits_set (hfmt, ufrom + 8);
371 1.1 skrll }
372 1.1 skrll }
373 1.1 skrll
374 1.1 skrll const struct floatformat floatformat_ibm_long_double =
375 1.1 skrll {
376 1.1 skrll floatformat_big, 128, 0, 1, 11, 1023, 2047, 12, 52,
377 1.1 skrll floatformat_intbit_no,
378 1.1 skrll "floatformat_ibm_long_double",
379 1.1 skrll floatformat_ibm_long_double_is_valid,
380 1.1 skrll &floatformat_ieee_double_big
381 1.1 skrll };
382 1.1 skrll
383 1.1 skrll
385 1.1 skrll #ifndef min
386 1.1 skrll #define min(a, b) ((a) < (b) ? (a) : (b))
387 1.1 skrll #endif
388 1.1 skrll
389 1.1 skrll /* Return 1 if any bits are explicitly set in the mantissa of UFROM,
390 1.1 skrll format FMT, 0 otherwise. */
391 1.1 skrll static int
392 1.1 skrll mant_bits_set (const struct floatformat *fmt, const unsigned char *ufrom)
393 1.1 skrll {
394 1.1 skrll unsigned int mant_bits, mant_off;
395 1.1 skrll int mant_bits_left;
396 1.1 skrll
397 1.1 skrll mant_off = fmt->man_start;
398 1.1 skrll mant_bits_left = fmt->man_len;
399 1.1 skrll while (mant_bits_left > 0)
400 1.1 skrll {
401 1.1 skrll mant_bits = min (mant_bits_left, 32);
402 1.1 skrll
403 1.1 skrll if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
404 1.1 skrll mant_off, mant_bits) != 0)
405 1.1 skrll return 1;
406 1.1 skrll
407 1.1 skrll mant_off += mant_bits;
408 1.1 skrll mant_bits_left -= mant_bits;
409 1.1 skrll }
410 1.1 skrll return 0;
411 1.1 skrll }
412 1.1 skrll
413 1.1 skrll /* Extract a field which starts at START and is LEN bits long. DATA and
414 1.1 skrll TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
415 1.1 skrll static unsigned long
416 1.1 skrll get_field (const unsigned char *data, enum floatformat_byteorders order,
417 1.1 skrll unsigned int total_len, unsigned int start, unsigned int len)
418 1.1 skrll {
419 1.1 skrll unsigned long result = 0;
420 1.1 skrll unsigned int cur_byte;
421 1.1 skrll int lo_bit, hi_bit, cur_bitshift = 0;
422 1.1 skrll int nextbyte = (order == floatformat_little) ? 1 : -1;
423 1.1 skrll
424 1.1 skrll /* Start is in big-endian bit order! Fix that first. */
425 1.1 skrll start = total_len - (start + len);
426 1.1 skrll
427 1.1 skrll /* Start at the least significant part of the field. */
428 1.1 skrll if (order == floatformat_little)
429 1.1 skrll cur_byte = start / FLOATFORMAT_CHAR_BIT;
430 1.1 skrll else
431 1.1 skrll cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
432 1.1 skrll
433 1.1 skrll lo_bit = start % FLOATFORMAT_CHAR_BIT;
434 1.1 skrll hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
435 1.1 skrll
436 1.1 skrll do
437 1.1 skrll {
438 1.1 skrll unsigned int shifted = *(data + cur_byte) >> lo_bit;
439 1.1 skrll unsigned int bits = hi_bit - lo_bit;
440 1.1 skrll unsigned int mask = (1 << bits) - 1;
441 1.1 skrll result |= (shifted & mask) << cur_bitshift;
442 1.1 skrll len -= bits;
443 1.1 skrll cur_bitshift += bits;
444 1.1 skrll cur_byte += nextbyte;
445 1.1 skrll lo_bit = 0;
446 1.1 skrll hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
447 1.1 skrll }
448 1.1 skrll while (len != 0);
449 1.1 skrll
450 1.1 skrll return result;
451 1.1 skrll }
452 1.1 skrll
453 1.1 skrll /* Convert from FMT to a double.
454 1.1 skrll FROM is the address of the extended float.
455 1.1 skrll Store the double in *TO. */
456 1.1 skrll
457 1.1 skrll void
458 1.1 skrll floatformat_to_double (const struct floatformat *fmt,
459 1.1 skrll const void *from, double *to)
460 1.1 skrll {
461 1.1 skrll const unsigned char *ufrom = (const unsigned char *) from;
462 1.1 skrll double dto;
463 1.1 skrll long exponent;
464 1.1 skrll unsigned long mant;
465 1.1 skrll unsigned int mant_bits, mant_off;
466 1.1 skrll int mant_bits_left;
467 1.1 skrll int special_exponent; /* It's a NaN, denorm or zero */
468 1.1 skrll
469 1.1 skrll /* Split values are not handled specially, since the top half has
470 1.1 skrll the correctly rounded double value (in the only supported case of
471 1.1 skrll split values). */
472 1.1 skrll
473 1.1 skrll exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
474 1.1 skrll fmt->exp_start, fmt->exp_len);
475 1.1 skrll
476 1.1 skrll /* If the exponent indicates a NaN, we don't have information to
477 1.1 skrll decide what to do. So we handle it like IEEE, except that we
478 1.1 skrll don't try to preserve the type of NaN. FIXME. */
479 1.1 skrll if ((unsigned long) exponent == fmt->exp_nan)
480 1.1 skrll {
481 1.1 skrll int nan = mant_bits_set (fmt, ufrom);
482 1.1 skrll
483 1.1 skrll /* On certain systems (such as GNU/Linux), the use of the
484 1.1 skrll INFINITY macro below may generate a warning that can not be
485 1.1 skrll silenced due to a bug in GCC (PR preprocessor/11931). The
486 1.1 skrll preprocessor fails to recognise the __extension__ keyword in
487 1.1 skrll conjunction with the GNU/C99 extension for hexadecimal
488 1.1 skrll floating point constants and will issue a warning when
489 1.1 skrll compiling with -pedantic. */
490 1.1 skrll if (nan)
491 1.1 skrll dto = NAN;
492 1.2 joerg else
493 1.2 joerg #ifdef __vax__
494 1.2 joerg dto = HUGE_VAL;
495 1.1 skrll #else
496 1.2 joerg dto = INFINITY;
497 1.1 skrll #endif
498 1.1 skrll
499 1.1 skrll if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
500 1.1 skrll dto = -dto;
501 1.1 skrll
502 1.1 skrll *to = dto;
503 1.1 skrll
504 1.1 skrll return;
505 1.1 skrll }
506 1.1 skrll
507 1.1 skrll mant_bits_left = fmt->man_len;
508 1.1 skrll mant_off = fmt->man_start;
509 1.1 skrll dto = 0.0;
510 1.1 skrll
511 1.1 skrll special_exponent = exponent == 0 || (unsigned long) exponent == fmt->exp_nan;
512 1.1 skrll
513 1.1 skrll /* Don't bias zero's, denorms or NaNs. */
514 1.1 skrll if (!special_exponent)
515 1.1 skrll exponent -= fmt->exp_bias;
516 1.1 skrll
517 1.1 skrll /* Build the result algebraically. Might go infinite, underflow, etc;
518 1.1 skrll who cares. */
519 1.1 skrll
520 1.1 skrll /* If this format uses a hidden bit, explicitly add it in now. Otherwise,
521 1.1 skrll increment the exponent by one to account for the integer bit. */
522 1.1 skrll
523 1.1 skrll if (!special_exponent)
524 1.1 skrll {
525 1.1 skrll if (fmt->intbit == floatformat_intbit_no)
526 1.1 skrll dto = ldexp (1.0, exponent);
527 1.1 skrll else
528 1.1 skrll exponent++;
529 1.1 skrll }
530 1.1 skrll
531 1.1 skrll while (mant_bits_left > 0)
532 1.1 skrll {
533 1.1 skrll mant_bits = min (mant_bits_left, 32);
534 1.1 skrll
535 1.1 skrll mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
536 1.1 skrll mant_off, mant_bits);
537 1.1 skrll
538 1.1 skrll /* Handle denormalized numbers. FIXME: What should we do for
539 1.1 skrll non-IEEE formats? */
540 1.1 skrll if (special_exponent && exponent == 0 && mant != 0)
541 1.1 skrll dto += ldexp ((double)mant,
542 1.1 skrll (- fmt->exp_bias
543 1.1 skrll - mant_bits
544 1.1 skrll - (mant_off - fmt->man_start)
545 1.1 skrll + 1));
546 1.1 skrll else
547 1.1 skrll dto += ldexp ((double)mant, exponent - mant_bits);
548 1.1 skrll if (exponent != 0)
549 1.1 skrll exponent -= mant_bits;
550 1.1 skrll mant_off += mant_bits;
551 1.1 skrll mant_bits_left -= mant_bits;
552 1.1 skrll }
553 1.1 skrll
554 1.1 skrll /* Negate it if negative. */
555 1.1 skrll if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
556 1.1 skrll dto = -dto;
557 1.1 skrll *to = dto;
558 1.1 skrll }
559 1.1 skrll
560 1.1 skrll static void put_field (unsigned char *, enum floatformat_byteorders,
562 1.1 skrll unsigned int,
563 1.1 skrll unsigned int,
564 1.1 skrll unsigned int,
565 1.1 skrll unsigned long);
566 1.1 skrll
567 1.1 skrll /* Set a field which starts at START and is LEN bits long. DATA and
568 1.1 skrll TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
569 1.1 skrll static void
570 1.1 skrll put_field (unsigned char *data, enum floatformat_byteorders order,
571 1.1 skrll unsigned int total_len, unsigned int start, unsigned int len,
572 1.1 skrll unsigned long stuff_to_put)
573 1.1 skrll {
574 1.1 skrll unsigned int cur_byte;
575 1.1 skrll int lo_bit, hi_bit;
576 1.1 skrll int nextbyte = (order == floatformat_little) ? 1 : -1;
577 1.1 skrll
578 1.1 skrll /* Start is in big-endian bit order! Fix that first. */
579 1.1 skrll start = total_len - (start + len);
580 1.1 skrll
581 1.1 skrll /* Start at the least significant part of the field. */
582 1.1 skrll if (order == floatformat_little)
583 1.1 skrll cur_byte = start / FLOATFORMAT_CHAR_BIT;
584 1.1 skrll else
585 1.1 skrll cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
586 1.1 skrll
587 1.1 skrll lo_bit = start % FLOATFORMAT_CHAR_BIT;
588 1.1 skrll hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
589 1.1 skrll
590 1.1 skrll do
591 1.1 skrll {
592 1.1 skrll unsigned char *byte_ptr = data + cur_byte;
593 1.1 skrll unsigned int bits = hi_bit - lo_bit;
594 1.1 skrll unsigned int mask = ((1 << bits) - 1) << lo_bit;
595 1.1 skrll *byte_ptr = (*byte_ptr & ~mask) | ((stuff_to_put << lo_bit) & mask);
596 1.1 skrll stuff_to_put >>= bits;
597 1.1 skrll len -= bits;
598 1.1 skrll cur_byte += nextbyte;
599 1.1 skrll lo_bit = 0;
600 1.1 skrll hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
601 1.1 skrll }
602 1.1 skrll while (len != 0);
603 1.1 skrll }
604 1.1 skrll
605 1.1 skrll /* The converse: convert the double *FROM to an extended float
606 1.1 skrll and store where TO points. Neither FROM nor TO have any alignment
607 1.1 skrll restrictions. */
608 1.1 skrll
609 1.1 skrll void
610 1.1 skrll floatformat_from_double (const struct floatformat *fmt,
611 1.1 skrll const double *from, void *to)
612 1.1 skrll {
613 1.1 skrll double dfrom;
614 1.1 skrll int exponent;
615 1.1 skrll double mant;
616 1.1 skrll unsigned int mant_bits, mant_off;
617 1.1 skrll int mant_bits_left;
618 1.1 skrll unsigned char *uto = (unsigned char *) to;
619 1.1 skrll
620 1.1 skrll dfrom = *from;
621 1.1 skrll memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
622 1.1 skrll
623 1.1 skrll /* Split values are not handled specially, since a bottom half of
624 1.1 skrll zero is correct for any value representable as double (in the
625 1.1 skrll only supported case of split values). */
626 1.1 skrll
627 1.1 skrll /* If negative, set the sign bit. */
628 1.1 skrll if (dfrom < 0)
629 1.1 skrll {
630 1.1 skrll put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
631 1.1 skrll dfrom = -dfrom;
632 1.1 skrll }
633 1.1 skrll
634 1.1 skrll if (dfrom == 0)
635 1.1 skrll {
636 1.1 skrll /* 0.0. */
637 1.1 skrll return;
638 1.1 skrll }
639 1.1 skrll
640 1.1 skrll if (dfrom != dfrom)
641 1.1 skrll {
642 1.1 skrll /* NaN. */
643 1.1 skrll put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
644 1.1 skrll fmt->exp_len, fmt->exp_nan);
645 1.1 skrll /* Be sure it's not infinity, but NaN value is irrelevant. */
646 1.1 skrll put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
647 1.1 skrll 32, 1);
648 1.1 skrll return;
649 1.1 skrll }
650 1.1 skrll
651 1.1 skrll if (dfrom + dfrom == dfrom)
652 1.1 skrll {
653 1.1 skrll /* This can only happen for an infinite value (or zero, which we
654 1.1 skrll already handled above). */
655 1.1 skrll put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
656 1.1 skrll fmt->exp_len, fmt->exp_nan);
657 1.1 skrll return;
658 1.1 skrll }
659 1.1 skrll
660 1.1 skrll mant = frexp (dfrom, &exponent);
661 1.1 skrll if (exponent + fmt->exp_bias - 1 > 0)
662 1.1 skrll put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
663 1.1 skrll fmt->exp_len, exponent + fmt->exp_bias - 1);
664 1.1 skrll else
665 1.1 skrll {
666 1.1 skrll /* Handle a denormalized number. FIXME: What should we do for
667 1.1 skrll non-IEEE formats? */
668 1.1 skrll put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
669 1.1 skrll fmt->exp_len, 0);
670 1.1 skrll mant = ldexp (mant, exponent + fmt->exp_bias - 1);
671 1.1 skrll }
672 1.1 skrll
673 1.1 skrll mant_bits_left = fmt->man_len;
674 1.1 skrll mant_off = fmt->man_start;
675 1.1 skrll while (mant_bits_left > 0)
676 1.1 skrll {
677 1.1 skrll unsigned long mant_long;
678 1.1 skrll mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
679 1.1 skrll
680 1.1 skrll mant *= 4294967296.0;
681 1.1 skrll mant_long = (unsigned long)mant;
682 1.1 skrll mant -= mant_long;
683 1.1 skrll
684 1.1 skrll /* If the integer bit is implicit, and we are not creating a
685 1.1 skrll denormalized number, then we need to discard it. */
686 1.1 skrll if ((unsigned int) mant_bits_left == fmt->man_len
687 1.1 skrll && fmt->intbit == floatformat_intbit_no
688 1.1 skrll && exponent + fmt->exp_bias - 1 > 0)
689 1.1 skrll {
690 1.1 skrll mant_long &= 0x7fffffff;
691 1.1 skrll mant_bits -= 1;
692 1.1 skrll }
693 1.1 skrll else if (mant_bits < 32)
694 1.1 skrll {
695 1.1 skrll /* The bits we want are in the most significant MANT_BITS bits of
696 1.1 skrll mant_long. Move them to the least significant. */
697 1.1 skrll mant_long >>= 32 - mant_bits;
698 1.1 skrll }
699 1.1 skrll
700 1.1 skrll put_field (uto, fmt->byteorder, fmt->totalsize,
701 1.1 skrll mant_off, mant_bits, mant_long);
702 1.1 skrll mant_off += mant_bits;
703 1.1 skrll mant_bits_left -= mant_bits;
704 1.1 skrll }
705 1.1 skrll }
706 1.1 skrll
707 1.1 skrll /* Return non-zero iff the data at FROM is a valid number in format FMT. */
708 1.1 skrll
709 1.1 skrll int
710 1.1 skrll floatformat_is_valid (const struct floatformat *fmt, const void *from)
711 1.1 skrll {
712 1.1 skrll return fmt->is_valid (fmt, from);
713 1.1 skrll }
714 1.1 skrll
715 1.1 skrll
716 1.1 skrll #ifdef IEEE_DEBUG
717 1.1 skrll
718 1.1 skrll #include <stdio.h>
719 1.1 skrll
720 1.1 skrll /* This is to be run on a host which uses IEEE floating point. */
721 1.1 skrll
722 1.1 skrll void
723 1.1 skrll ieee_test (double n)
724 1.1 skrll {
725 1.1 skrll double result;
726 1.1 skrll
727 1.1 skrll floatformat_to_double (&floatformat_ieee_double_little, &n, &result);
728 1.1 skrll if ((n != result && (! isnan (n) || ! isnan (result)))
729 1.1 skrll || (n < 0 && result >= 0)
730 1.1 skrll || (n >= 0 && result < 0))
731 1.1 skrll printf ("Differ(to): %.20g -> %.20g\n", n, result);
732 1.1 skrll
733 1.1 skrll floatformat_from_double (&floatformat_ieee_double_little, &n, &result);
734 1.1 skrll if ((n != result && (! isnan (n) || ! isnan (result)))
735 1.1 skrll || (n < 0 && result >= 0)
736 1.1 skrll || (n >= 0 && result < 0))
737 1.1 skrll printf ("Differ(from): %.20g -> %.20g\n", n, result);
738 1.1 skrll
739 1.1 skrll #if 0
740 1.1 skrll {
741 1.1 skrll char exten[16];
742 1.1 skrll
743 1.1 skrll floatformat_from_double (&floatformat_m68881_ext, &n, exten);
744 1.1 skrll floatformat_to_double (&floatformat_m68881_ext, exten, &result);
745 1.1 skrll if (n != result)
746 1.1 skrll printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
747 1.1 skrll }
748 1.1 skrll #endif
749 1.1 skrll
750 1.1 skrll #if IEEE_DEBUG > 1
751 1.1 skrll /* This is to be run on a host which uses 68881 format. */
752 1.1 skrll {
753 1.1 skrll long double ex = *(long double *)exten;
754 1.1 skrll if (ex != n)
755 1.1 skrll printf ("Differ(from vs. extended): %.20g\n", n);
756 1.1 skrll }
757 1.1 skrll #endif
758 1.1 skrll }
759 1.1 skrll
760 1.1 skrll int
761 1.1 skrll main (void)
762 1.1 skrll {
763 1.1 skrll ieee_test (0.0);
764 1.1 skrll ieee_test (0.5);
765 1.1 skrll ieee_test (256.0);
766 1.1 skrll ieee_test (0.12345);
767 1.1 skrll ieee_test (234235.78907234);
768 1.1 skrll ieee_test (-512.0);
769 1.1 skrll ieee_test (-0.004321);
770 1.1 skrll ieee_test (1.2E-70);
771 1.1 skrll ieee_test (1.2E-316);
772 1.1 skrll ieee_test (4.9406564584124654E-324);
773 1.1 skrll ieee_test (- 4.9406564584124654E-324);
774 1.1 skrll ieee_test (- 0.0);
775 1.1 skrll ieee_test (- INFINITY);
776 1.1 skrll ieee_test (- NAN);
777 1.1 skrll ieee_test (INFINITY);
778 1.1 skrll ieee_test (NAN);
779 1.1 skrll return 0;
780 }
781 #endif
782