|
|
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.