1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22: #define _GNU_SOURCE
23:
24: #ifdef HAVE_CONFIG_H
25: #include "config.h"
26: #endif
27:
28: #include <math.h>
29:
30: #ifdef HAVE_STRING_H
31: #include <string.h>
32: #endif
33:
34:
35: #ifdef STDC_HEADERS
36: #include <float.h>
37: #endif
38:
39: #include "ansidecl.h"
40: #include "libiberty.h"
41: #include "floatformat.h"
42:
43: #ifndef INFINITY
44: #ifdef HUGE_VAL
45: #define INFINITY HUGE_VAL
46: #else
47: #define INFINITY (1.0 / 0.0)
48: #endif
49: #endif
50:
51: #ifndef NAN
52: #ifdef DBL_QNAN
53: #define NAN DBL_QNAN
54: #else
55: #define NAN (0.0 / 0.0)
56: #endif
57: #endif
58:
59: static unsigned long get_field (const unsigned char *,
60: enum floatformat_byteorders,
61: unsigned int,
62: unsigned int,
63: unsigned int);
64: static int floatformat_always_valid (const struct floatformat *fmt,
65: const void *from);
66:
67: static int
68: floatformat_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED,
69: const void *from ATTRIBUTE_UNUSED)
70: {
71: return 1;
72: }
73:
74:
75:
76:
77: #define FLOATFORMAT_CHAR_BIT 8
78:
79:
80: const struct floatformat floatformat_ieee_single_big =
81: {
82: floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23,
83: floatformat_intbit_no,
84: "floatformat_ieee_single_big",
85: floatformat_always_valid
86: };
87: const struct floatformat floatformat_ieee_single_little =
88: {
89: floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23,
90: floatformat_intbit_no,
91: "floatformat_ieee_single_little",
92: floatformat_always_valid
93: };
94: const struct floatformat floatformat_ieee_double_big =
95: {
96: floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52,
97: floatformat_intbit_no,
98: "floatformat_ieee_double_big",
99: floatformat_always_valid
100: };
101: const struct floatformat floatformat_ieee_double_little =
102: {
103: floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52,
104: floatformat_intbit_no,
105: "floatformat_ieee_double_little",
106: floatformat_always_valid
107: };
108:
109:
110:
111:
112: const struct floatformat floatformat_ieee_double_littlebyte_bigword =
113: {
114: floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52,
115: floatformat_intbit_no,
116: "floatformat_ieee_double_littlebyte_bigword",
117: floatformat_always_valid
118: };
119:
120:
121:
122: const struct floatformat floatformat_vax_f =
123: {
124: floatformat_vax, 32, 0, 1, 8, 129, 0, 9, 23,
125: floatformat_intbit_no,
126: "floatformat_vax_f",
127: floatformat_always_valid
128: };
129: const struct floatformat floatformat_vax_d =
130: {
131: floatformat_vax, 64, 0, 1, 8, 129, 0, 9, 55,
132: floatformat_intbit_no,
133: "floatformat_vax_d",
134: floatformat_always_valid
135: };
136: const struct floatformat floatformat_vax_g =
137: {
138: floatformat_vax, 64, 0, 1, 11, 1025, 0, 12, 52,
139: floatformat_intbit_no,
140: "floatformat_vax_g",
141: floatformat_always_valid
142: };
143:
144: static int floatformat_i387_ext_is_valid (const struct floatformat *fmt,
145: const void *from);
146:
147: static int
148: floatformat_i387_ext_is_valid (const struct floatformat *fmt, const void *from)
149: {
150:
151:
152:
153:
154: unsigned long exponent, int_bit;
155: const unsigned char *ufrom = (const unsigned char *) from;
156:
157: exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
158: fmt->exp_start, fmt->exp_len);
159: int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize,
160: fmt->man_start, 1);
161:
162: if ((exponent == 0) != (int_bit == 0))
163: return 0;
164: else
165: return 1;
166: }
167:
168: const struct floatformat floatformat_i387_ext =
169: {
170: floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
171: floatformat_intbit_yes,
172: "floatformat_i387_ext",
173: floatformat_i387_ext_is_valid
174: };
175: const struct floatformat floatformat_m68881_ext =
176: {
177:
178: floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
179: floatformat_intbit_yes,
180: "floatformat_m68881_ext",
181: floatformat_always_valid
182: };
183: const struct floatformat floatformat_i960_ext =
184: {
185:
186: floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
187: floatformat_intbit_yes,
188: "floatformat_i960_ext",
189: floatformat_always_valid
190: };
191: const struct floatformat floatformat_m88110_ext =
192: {
193: floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
194: floatformat_intbit_yes,
195: "floatformat_m88110_ext",
196: floatformat_always_valid
197: };
198: const struct floatformat floatformat_m88110_harris_ext =
199: {
200:
201:
202: floatformat_big,128, 0, 1, 11, 0x3ff, 0x7ff, 12, 52,
203: floatformat_intbit_no,
204: "floatformat_m88110_ext_harris",
205: floatformat_always_valid
206: };
207: const struct floatformat floatformat_arm_ext_big =
208: {
209:
210: floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
211: floatformat_intbit_yes,
212: "floatformat_arm_ext_big",
213: floatformat_always_valid
214: };
215: const struct floatformat floatformat_arm_ext_littlebyte_bigword =
216: {
217:
218: floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
219: floatformat_intbit_yes,
220: "floatformat_arm_ext_littlebyte_bigword",
221: floatformat_always_valid
222: };
223: const struct floatformat floatformat_ia64_spill_big =
224: {
225: floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
226: floatformat_intbit_yes,
227: "floatformat_ia64_spill_big",
228: floatformat_always_valid
229: };
230: const struct floatformat floatformat_ia64_spill_little =
231: {
232: floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
233: floatformat_intbit_yes,
234: "floatformat_ia64_spill_little",
235: floatformat_always_valid
236: };
237: const struct floatformat floatformat_ia64_quad_big =
238: {
239: floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
240: floatformat_intbit_no,
241: "floatformat_ia64_quad_big",
242: floatformat_always_valid
243: };
244: const struct floatformat floatformat_ia64_quad_little =
245: {
246: floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
247: floatformat_intbit_no,
248: "floatformat_ia64_quad_little",
249: floatformat_always_valid
250: };
251: ^L
252:
253: #ifndef min
254: #define min(a, b) ((a) < (b) ? (a) : (b))
255: #endif
256:
257:
258:
259: static unsigned long
260: get_field (const unsigned char *data, enum floatformat_byteorders order,
261: unsigned int total_len, unsigned int start, unsigned int len)
262: {
263: unsigned long result = 0;
264: unsigned int cur_byte;
265: int lo_bit, hi_bit, cur_bitshift = 0;
266: int nextbyte = (order == floatformat_little) ? 1 : -1;
267:
268:
269: start = total_len - (start + len);
270:
271:
272: if (order == floatformat_little)
273: cur_byte = start / FLOATFORMAT_CHAR_BIT;
274: else
275: cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
276:
277: lo_bit = start % FLOATFORMAT_CHAR_BIT;
278: hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
279:
280: do
281: {
282: unsigned int shifted = *(data + cur_byte) >> lo_bit;
283: unsigned int bits = hi_bit - lo_bit;
284: unsigned int mask = (1 << bits) - 1;
285: result |= (shifted & mask) << cur_bitshift;
286: len -= bits;
287: cur_bitshift += bits;
288: cur_byte += nextbyte;
289: lo_bit = 0;
290: hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
291: }
292: while (len != 0);
293:
294: return result;
295: }
296:
297:
298:
299:
300:
301: void
302: floatformat_to_double (const struct floatformat *fmt,
303: const void *from, double *to)
304: {
305: const unsigned char *ufrom = (const unsigned char *) from;
306: double dto;
307: long exponent;
308: unsigned long mant;
309: unsigned int mant_bits, mant_off;
310: int mant_bits_left;
311: int special_exponent;
312:
313: exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
314: fmt->exp_start, fmt->exp_len);
315:
316:
317:
318:
319: if ((unsigned long) exponent == fmt->exp_nan)
320: {
321: int nan;
322:
323: mant_off = fmt->man_start;
324: mant_bits_left = fmt->man_len;
325: nan = 0;
326: while (mant_bits_left > 0)
327: {
328: mant_bits = min (mant_bits_left, 32);
329:
330: if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
331: mant_off, mant_bits) != 0)
332: {
333:
334: nan = 1;
335: break;
336: }
337:
338: mant_off += mant_bits;
339: mant_bits_left -= mant_bits;
340: }
341:
342:
343:
344:
345:
346:
347:
348:
349: if (nan)
350: dto = NAN;
351: else
352: dto = INFINITY;
353:
354: if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
355: dto = -dto;
356:
357: *to = dto;
358:
359: return;
360: }
361:
362: mant_bits_left = fmt->man_len;
363: mant_off = fmt->man_start;
364: dto = 0.0;
365:
366: special_exponent = exponent == 0 || (unsigned long) exponent == fmt->exp_nan;
367:
368:
369: if (!special_exponent)
370: exponent -= fmt->exp_bias;
371:
372:
373:
374:
375:
376:
377:
378: if (!special_exponent)
379: {
380: if (fmt->intbit == floatformat_intbit_no)
381: dto = ldexp (1.0, exponent);
382: else
383: exponent++;
384: }
385:
386: while (mant_bits_left > 0)
387: {
388: mant_bits = min (mant_bits_left, 32);
389:
390: mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
391: mant_off, mant_bits);
392:
393:
394:
395: if (special_exponent && exponent == 0 && mant != 0)
396: dto += ldexp ((double)mant,
397: (- fmt->exp_bias
398: - mant_bits
399: - (mant_off - fmt->man_start)
400: + 1));
401: else
402: dto += ldexp ((double)mant, exponent - mant_bits);
403: if (exponent != 0)
404: exponent -= mant_bits;
405: mant_off += mant_bits;
406: mant_bits_left -= mant_bits;
407: }
408:
409:
410: if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
411: dto = -dto;
412: *to = dto;
413: }
414: ^L
415: static void put_field (unsigned char *, enum floatformat_byteorders,
416: unsigned int,
417: unsigned int,
418: unsigned int,
419: unsigned long);
420:
421:
422:
423: static void
424: put_field (unsigned char *data, enum floatformat_byteorders order,
425: unsigned int total_len, unsigned int start, unsigned int len,
426: unsigned long stuff_to_put)
427: {
428: unsigned int cur_byte;
429: int lo_bit, hi_bit;
430: int nextbyte = (order == floatformat_little) ? 1 : -1;
431:
432:
433: start = total_len - (start + len);
434:
435:
436: if (order == floatformat_little)
437: cur_byte = start / FLOATFORMAT_CHAR_BIT;
438: else
439: cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
440:
441: lo_bit = start % FLOATFORMAT_CHAR_BIT;
442: hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
443:
444: do
445: {
446: unsigned char *byte_ptr = data + cur_byte;
447: unsigned int bits = hi_bit - lo_bit;
448: unsigned int mask = ((1 << bits) - 1) << lo_bit;
449: *byte_ptr = (*byte_ptr & ~mask) | ((stuff_to_put << lo_bit) & mask);
450: stuff_to_put >>= bits;
451: len -= bits;
452: cur_byte += nextbyte;
453: lo_bit = 0;
454: hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
455: }
456: while (len != 0);
457: }
458:
459:
460:
461:
462:
463: void
464: floatformat_from_double (const struct floatformat *fmt,
465: const double *from, void *to)
466: {
467: double dfrom;
468: int exponent;
469: double mant;
470: unsigned int mant_bits, mant_off;
471: int mant_bits_left;
472: unsigned char *uto = (unsigned char *) to;
473:
474: dfrom = *from;
475: memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
476:
477:
478: if (dfrom < 0)
479: {
480: put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
481: dfrom = -dfrom;
482: }
483:
484: if (dfrom == 0)
485: {
486:
487: return;
488: }
489:
490: if (dfrom != dfrom)
491: {
492:
493: put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
494: fmt->exp_len, fmt->exp_nan);
495:
496: put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
497: 32, 1);
498: return;
499: }
500:
501: if (dfrom + dfrom == dfrom)
502: {
503:
504:
505: put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
506: fmt->exp_len, fmt->exp_nan);
507: return;
508: }
509:
510: mant = frexp (dfrom, &exponent);
511: if (exponent + fmt->exp_bias - 1 > 0)
512: put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
513: fmt->exp_len, exponent + fmt->exp_bias - 1);
514: else
515: {
516:
517:
518: put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
519: fmt->exp_len, 0);
520: mant = ldexp (mant, exponent + fmt->exp_bias - 1);
521: }
522:
523: mant_bits_left = fmt->man_len;
524: mant_off = fmt->man_start;
525: while (mant_bits_left > 0)
526: {
527: unsigned long mant_long;
528: mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
529:
530: mant *= 4294967296.0;
531: mant_long = (unsigned long)mant;
532: mant -= mant_long;
533:
534:
535:
536: if ((unsigned int) mant_bits_left == fmt->man_len
537: && fmt->intbit == floatformat_intbit_no
538: && exponent + fmt->exp_bias - 1 > 0)
539: {
540: mant_long &= 0x7fffffff;
541: mant_bits -= 1;
542: }
543: else if (mant_bits < 32)
544: {
545:
546: