|
|
1.1 root 1: /* IEEE floating point support routines, for GDB, the GNU Debugger.
2: Copyright (C) 1991 Free Software Foundation, Inc.
3:
4: This file is part of GDB.
5:
6: This program is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 2 of the License, or
9: (at your option) any later version.
10:
11: This program is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with this program; if not, write to the Free Software
18: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19:
20: #include "ieee-float.h"
21: #include <math.h> /* ldexp */
22:
23: /* Convert an IEEE extended float to a double.
24: FROM is the address of the extended float.
25: Store the double in *TO. */
26:
27: void
28: ieee_extended_to_double (ext_format, from, to)
29: CONST struct ext_format *ext_format;
30: char *from;
31: double *to;
32: {
33: unsigned char *ufrom = (unsigned char *)from;
34: double dto;
35: unsigned long mant0, mant1, exponent;
36:
37: memcpy (&mant0, &from[MANBYTE_H], 4);
38: memcpy (&mant1, &from[MANBYTE_L], 4);
39: exponent = ((ufrom[EXPBYTE_H] & (unsigned char)~SIGNMASK) << 8) | ufrom[EXPBYTE_L];
40:
41: #if 0
42: /* We can't do anything useful with a NaN anyway, so ignore its
43: difference. It will end up as Infinity or something close. */
44: if (exponent == EXT_EXP_NAN) {
45: /* We have a NaN source. */
46: dto = 0.123456789; /* Not much else useful to do -- we don't know if
47: the host system even *has* NaNs, nor how to
48: generate an innocuous one if it does. */
49: } else
50: #endif
51: if (exponent == 0 && mant0 == 0 && mant1 == 0) {
52: dto = 0;
53: } else {
54: /* Build the result algebraically. Might go infinite, underflow, etc;
55: who cares. */
56: mant0 |= 0x80000000;
57: dto = ldexp ((double)mant0, exponent - EXT_EXP_BIAS - 31);
58: dto += ldexp ((double)mant1, exponent - EXT_EXP_BIAS - 31 - 32);
59: if (ufrom[EXPBYTE_H] & SIGNMASK) /* If negative... */
60: dto = -dto; /* ...negate. */
61: }
62: memcpy (to, &dto, sizeof (dto));
63: }
64:
65: /* The converse: convert the double *FROM to an extended float
66: and store where TO points. Neither FROM nor TO have any alignment
67: restrictions. */
68:
69: void
70: double_to_ieee_extended (ext_format, from, to)
71: CONST struct ext_format *ext_format;
72: double *from;
73: char *to;
74: {
75: double dfrom;
76: unsigned long twolongs[2];
77: unsigned long mant0, mant1, exponent;
78: unsigned char tobytes[8];
79:
80: memcpy (&dfrom, from, sizeof (dfrom));
81: memset (to, 0, TOTALSIZE);
82: if (dfrom == 0)
83: return; /* Result is zero */
84: if (dfrom != dfrom) {
85: /* From is NaN */
86: to[EXPBYTE_H] = (unsigned char)(EXT_EXP_NAN >> 8);
87: to[EXPBYTE_L] = (unsigned char)EXT_EXP_NAN;
88: to[MANBYTE_H] = 1; /* Be sure it's not infinity, but NaN value is irrel */
89: return; /* Result is NaN */
90: }
91: if (dfrom < 0)
92: to[SIGNBYTE] |= SIGNMASK; /* Set negative sign */
93: /* How to tell an infinity from an ordinary number? FIXME-someday */
94:
95: /* The following code assumes that the host has IEEE doubles. FIXME-someday.
96: It also assumes longs are 32 bits! FIXME-someday. */
97: memcpy (twolongs, from, 8);
98: memcpy (tobytes, from, 8);
99: #if HOST_BYTE_ORDER == BIG_ENDIAN
100: exponent = ((tobytes[1] & 0xF0) >> 4) | (tobytes[0] & 0x7F) << 4;
101: mant0 = (twolongs[0] << 11) | twolongs[1] >> 21;
102: mant1 = (twolongs[1] << 11);
103: #else
104: exponent = ((tobytes[6] & 0xF0) >> 4) | (tobytes[7] & 0x7F) << 4;
105: mant0 = (twolongs[1] << 11) | twolongs[0] >> 21;
106: mant1 = (twolongs[0] << 11);
107: #endif
108:
109: /* Fiddle with leading 1-bit, implied in double, explicit in extended. */
110: if (exponent == 0)
111: mant0 &= 0x7FFFFFFF;
112: else
113: mant0 |= 0x80000000;
114:
115: exponent -= DBL_EXP_BIAS; /* Get integer exp */
116: exponent += EXT_EXP_BIAS; /* Offset for extended */
117:
118: /* OK, now store it in extended format. */
119: to[EXPBYTE_H] |= (unsigned char)(exponent >> 8); /* Retain sign */
120: to[EXPBYTE_L] = (unsigned char) exponent;
121:
122: memcpy (&to[MANBYTE_H], &mant0, 4);
123: memcpy (&to[MANBYTE_L], &mant1, 4);
124: }
125:
126:
127: #ifdef IEEE_DEBUG
128:
129: /* Test some numbers to see that extended/double conversion works for them. */
130:
131: ieee_test (n)
132: int n;
133: {
134: union { double d; int i[2]; } di;
135: double result;
136: int i;
137: char exten[16];
138: extern struct ext_format ext_format_68881;
139:
140: for (i = 0; i < n; i++) {
141: di.i[0] = (random() << 16) | (random() & 0xffff);
142: di.i[1] = (random() << 16) | (random() & 0xffff);
143: double_to_ieee_extended (&ext_format_68881, &di.d, exten);
144: ieee_extended_to_double (&ext_format_68881, exten, &result);
145: if (di.d != result)
146: printf ("Differ: %x %x %g => %x %x %g\n", di.d, di.d, result, result);
147: }
148: }
149:
150: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.