X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Fatof-ieee.c;h=443d28c2c4f8b0fbce4e0858b715593c1cbf3975;hb=eb408eaac923140f561d8307cb63da9c9550096a;hp=a5782c4fce90fea1db7bbfca20c2479dc67a58fc;hpb=355afbcd8b1a0253180ac565f8e7a18afdfc5977;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/atof-ieee.c b/gas/config/atof-ieee.c index a5782c4fce..443d28c2c4 100644 --- a/gas/config/atof-ieee.c +++ b/gas/config/atof-ieee.c @@ -1,11 +1,11 @@ /* atof_ieee.c - turn a Flonum into an IEEE floating point number - Copyright (C) 1987, 1992 Free Software Foundation, Inc. + Copyright (C) 1987-2016 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. GAS is distributed in the hope that it will be useful, @@ -14,29 +14,31 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with GAS; see the file COPYING. If not, write to - the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ #include "as.h" -extern FLONUM_TYPE generic_floating_point_number; /* Flonums returned here. */ +/* Flonums returned here. */ +extern FLONUM_TYPE generic_floating_point_number; -#ifndef NULL -#define NULL (0) -#endif +/* Precision in LittleNums. */ +/* Don't count the gap in the m68k extended precision format. */ +#define MAX_PRECISION 5 +#define F_PRECISION 2 +#define D_PRECISION 4 +#define X_PRECISION 5 +#define P_PRECISION 5 -extern const char EXP_CHARS[]; -/* Precision in LittleNums. */ -#define MAX_PRECISION (6) -#define F_PRECISION (2) -#define D_PRECISION (4) -#define X_PRECISION (6) -#define P_PRECISION (6) +/* Length in LittleNums of guard bits. */ +#define GUARD 2 -/* Length in LittleNums of guard bits. */ -#define GUARD (2) +#ifndef TC_LARGEST_EXPONENT_IS_NORMAL +#define TC_LARGEST_EXPONENT_IS_NORMAL(PRECISION) 0 +#endif -static unsigned long mask[] = +static const unsigned long mask[] = { 0x00000000, 0x00000001, @@ -73,19 +75,18 @@ static unsigned long mask[] = 0xffffffff, }; - static int bits_left_in_littlenum; static int littlenums_left; static LITTLENUM_TYPE *littlenum_pointer; static int -next_bits (number_of_bits) - int number_of_bits; +next_bits (int number_of_bits) { int return_value; if (!littlenums_left) - return (0); + return 0; + if (number_of_bits >= bits_left_in_littlenum) { return_value = mask[bits_left_in_littlenum] & *littlenum_pointer; @@ -96,21 +97,24 @@ next_bits (number_of_bits) { bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits; --littlenum_pointer; - return_value |= (*littlenum_pointer >> bits_left_in_littlenum) & mask[number_of_bits]; + return_value |= + (*littlenum_pointer >> bits_left_in_littlenum) + & mask[number_of_bits]; } } else { bits_left_in_littlenum -= number_of_bits; - return_value = mask[number_of_bits] & (*littlenum_pointer >> bits_left_in_littlenum); + return_value = + mask[number_of_bits] & (*littlenum_pointer >> bits_left_in_littlenum); } - return (return_value); + return return_value; } -/* Num had better be less than LITTLENUM_NUMBER_OF_BITS */ +/* Num had better be less than LITTLENUM_NUMBER_OF_BITS. */ + static void -unget_bits (num) - int num; +unget_bits (int num) { if (!littlenums_left) { @@ -120,7 +124,8 @@ unget_bits (num) } else if (bits_left_in_littlenum + num > LITTLENUM_NUMBER_OF_BITS) { - bits_left_in_littlenum = num - (LITTLENUM_NUMBER_OF_BITS - bits_left_in_littlenum); + bits_left_in_littlenum = + num - (LITTLENUM_NUMBER_OF_BITS - bits_left_in_littlenum); ++littlenum_pointer; ++littlenums_left; } @@ -129,61 +134,57 @@ unget_bits (num) } static void -make_invalid_floating_point_number (words) - LITTLENUM_TYPE *words; +make_invalid_floating_point_number (LITTLENUM_TYPE *words) { - as_bad ("cannot create floating-point number"); - words[0] = ((unsigned) -1) >> 1; /* Zero the leftmost bit */ - words[1] = -1; - words[2] = -1; - words[3] = -1; - words[4] = -1; - words[5] = -1; + as_bad (_("cannot create floating-point number")); + /* Zero the leftmost bit. */ + words[0] = (LITTLENUM_TYPE) ((unsigned) -1) >> 1; + words[1] = (LITTLENUM_TYPE) -1; + words[2] = (LITTLENUM_TYPE) -1; + words[3] = (LITTLENUM_TYPE) -1; + words[4] = (LITTLENUM_TYPE) -1; + words[5] = (LITTLENUM_TYPE) -1; } -/***********************************************************************\ - * Warning: this returns 16-bit LITTLENUMs. It is up to the caller * - * to figure out any alignment problems and to conspire for the * - * bytes/word to be emitted in the right order. Bigendians beware! * - * * - \***********************************************************************/ +/* Warning: This returns 16-bit LITTLENUMs. It is up to the caller to + figure out any alignment problems and to conspire for the + bytes/word to be emitted in the right order. Bigendians beware! */ /* Note that atof-ieee always has X and P precisions enabled. it is up to md_atof to filter them out if the target machine does not support them. */ -char * /* Return pointer past text consumed. */ -atof_ieee (str, what_kind, words) - char *str; /* Text to convert to binary. */ - char what_kind; /* 'd', 'f', 'g', 'h' */ - LITTLENUM_TYPE *words; /* Build the binary here. */ +/* Returns pointer past text consumed. */ + +char * +atof_ieee (char *str, /* Text to convert to binary. */ + int what_kind, /* 'd', 'f', 'x', 'p'. */ + LITTLENUM_TYPE *words) /* Build the binary here. */ { + /* Extra bits for zeroed low-order bits. + The 1st MAX_PRECISION are zeroed, the last contain flonum bits. */ static LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD]; - /* Extra bits for zeroed low-order bits. */ - /* The 1st MAX_PRECISION are zeroed, */ - /* the last contain flonum bits. */ char *return_value; - int precision; /* Number of 16-bit words in the format. */ + /* Number of 16-bit words in the format. */ + int precision; long exponent_bits; FLONUM_TYPE save_gen_flonum; /* We have to save the generic_floating_point_number because it - contains storage allocation about the array of LITTLENUMs - where the value is actually stored. We will allocate our - own array of littlenums below, but have to restore the global - one on exit. */ + contains storage allocation about the array of LITTLENUMs where + the value is actually stored. We will allocate our own array of + littlenums below, but have to restore the global one on exit. */ save_gen_flonum = generic_floating_point_number; return_value = str; generic_floating_point_number.low = bits + MAX_PRECISION; generic_floating_point_number.high = NULL; generic_floating_point_number.leader = NULL; - generic_floating_point_number.exponent = NULL; + generic_floating_point_number.exponent = 0; generic_floating_point_number.sign = '\0'; - /* Use more LittleNums than seems */ - /* necessary: the highest flonum may have */ - /* 15 leading 0 bits, so could be useless. */ + /* Use more LittleNums than seems necessary: the highest flonum may + have 15 leading 0 bits, so could be useless. */ memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION); @@ -215,7 +216,6 @@ atof_ieee (str, what_kind, words) case 'p': case 'P': - precision = P_PRECISION; exponent_bits = -1; break; @@ -225,29 +225,28 @@ atof_ieee (str, what_kind, words) return (NULL); } - generic_floating_point_number.high = generic_floating_point_number.low + precision - 1 + GUARD; + generic_floating_point_number.high + = generic_floating_point_number.low + precision - 1 + GUARD; - if (atof_generic (&return_value, ".", EXP_CHARS, &generic_floating_point_number)) + if (atof_generic (&return_value, ".", EXP_CHARS, + &generic_floating_point_number)) { - /* as_bad("Error converting floating point number (Exponent overflow?)"); */ make_invalid_floating_point_number (words); - return (NULL); + return NULL; } gen_to_words (words, precision, exponent_bits); - /* Restore the generic_floating_point_number's storage alloc - (and everything else). */ + /* Restore the generic_floating_point_number's storage alloc (and + everything else). */ generic_floating_point_number = save_gen_flonum; - return (return_value); + return return_value; } -/* Turn generic_floating_point_number into a real float/double/extended */ +/* Turn generic_floating_point_number into a real float/double/extended. */ + int -gen_to_words (words, precision, exponent_bits) - LITTLENUM_TYPE *words; - int precision; - long exponent_bits; +gen_to_words (LITTLENUM_TYPE *words, int precision, long exponent_bits) { int return_value = 0; @@ -258,26 +257,59 @@ gen_to_words (words, precision, exponent_bits) int exponent_skippage; LITTLENUM_TYPE word1; LITTLENUM_TYPE *lp; + LITTLENUM_TYPE *words_end; + + words_end = words + precision; +#ifdef TC_M68K + if (precision == X_PRECISION) + /* On the m68k the extended precision format has a gap of 16 bits + between the exponent and the mantissa. */ + words_end++; +#endif if (generic_floating_point_number.low > generic_floating_point_number.leader) { - /* 0.0e0 seen. */ + /* 0.0e0 seen. */ if (generic_floating_point_number.sign == '+') words[0] = 0x0000; else words[0] = 0x8000; - memset (&words[1], '\0', sizeof (LITTLENUM_TYPE) * (precision - 1)); - return (return_value); + memset (&words[1], '\0', + (words_end - words - 1) * sizeof (LITTLENUM_TYPE)); + return return_value; } - /* NaN: Do the right thing */ + /* NaN: Do the right thing. */ if (generic_floating_point_number.sign == 0) { + if (TC_LARGEST_EXPONENT_IS_NORMAL (precision)) + as_warn (_("NaNs are not supported by this target\n")); if (precision == F_PRECISION) { words[0] = 0x7fff; words[1] = 0xffff; } + else if (precision == X_PRECISION) + { +#ifdef TC_M68K + words[0] = 0x7fff; + words[1] = 0; + words[2] = 0xffff; + words[3] = 0xffff; + words[4] = 0xffff; + words[5] = 0xffff; +#else /* ! TC_M68K */ +#ifdef TC_I386 + words[0] = 0xffff; + words[1] = 0xc000; + words[2] = 0; + words[3] = 0; + words[4] = 0; +#else /* ! TC_I386 */ + abort (); +#endif /* ! TC_I386 */ +#endif /* ! TC_M68K */ + } else { words[0] = 0x7fff; @@ -289,12 +321,36 @@ gen_to_words (words, precision, exponent_bits) } else if (generic_floating_point_number.sign == 'P') { - /* +INF: Do the right thing */ + if (TC_LARGEST_EXPONENT_IS_NORMAL (precision)) + as_warn (_("Infinities are not supported by this target\n")); + + /* +INF: Do the right thing. */ if (precision == F_PRECISION) { words[0] = 0x7f80; words[1] = 0; } + else if (precision == X_PRECISION) + { +#ifdef TC_M68K + words[0] = 0x7fff; + words[1] = 0; + words[2] = 0; + words[3] = 0; + words[4] = 0; + words[5] = 0; +#else /* ! TC_M68K */ +#ifdef TC_I386 + words[0] = 0x7fff; + words[1] = 0x8000; + words[2] = 0; + words[3] = 0; + words[4] = 0; +#else /* ! TC_I386 */ + abort (); +#endif /* ! TC_I386 */ +#endif /* ! TC_M68K */ + } else { words[0] = 0x7ff0; @@ -302,16 +358,40 @@ gen_to_words (words, precision, exponent_bits) words[2] = 0; words[3] = 0; } - return (return_value); + return return_value; } else if (generic_floating_point_number.sign == 'N') { - /* Negative INF */ + if (TC_LARGEST_EXPONENT_IS_NORMAL (precision)) + as_warn (_("Infinities are not supported by this target\n")); + + /* Negative INF. */ if (precision == F_PRECISION) { words[0] = 0xff80; words[1] = 0x0; } + else if (precision == X_PRECISION) + { +#ifdef TC_M68K + words[0] = 0xffff; + words[1] = 0; + words[2] = 0; + words[3] = 0; + words[4] = 0; + words[5] = 0; +#else /* ! TC_M68K */ +#ifdef TC_I386 + words[0] = 0xffff; + words[1] = 0x8000; + words[2] = 0; + words[3] = 0; + words[4] = 0; +#else /* ! TC_I386 */ + abort (); +#endif /* ! TC_I386 */ +#endif /* ! TC_M68K */ + } else { words[0] = 0xfff0; @@ -319,67 +399,85 @@ gen_to_words (words, precision, exponent_bits) words[2] = 0x0; words[3] = 0x0; } - return (return_value); + return return_value; } - /* - * The floating point formats we support have: - * Bit 15 is sign bit. - * Bits 14:n are excess-whatever exponent. - * Bits n-1:0 (if any) are most significant bits of fraction. - * Bits 15:0 of the next word(s) are the next most significant bits. - * - * So we need: number of bits of exponent, number of bits of - * mantissa. - */ + + /* The floating point formats we support have: + Bit 15 is sign bit. + Bits 14:n are excess-whatever exponent. + Bits n-1:0 (if any) are most significant bits of fraction. + Bits 15:0 of the next word(s) are the next most significant bits. + + So we need: number of bits of exponent, number of bits of + mantissa. */ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; littlenum_pointer = generic_floating_point_number.leader; - littlenums_left = 1 + generic_floating_point_number.leader - generic_floating_point_number.low; - /* Seek (and forget) 1st significant bit */ - for (exponent_skippage = 0; !next_bits (1); ++exponent_skippage);; - exponent_1 = generic_floating_point_number.exponent + generic_floating_point_number.leader - + 1 - generic_floating_point_number.low; - /* Radix LITTLENUM_RADIX, point just higher than generic_floating_point_number.leader. */ + littlenums_left = (1 + + generic_floating_point_number.leader + - generic_floating_point_number.low); + + /* Seek (and forget) 1st significant bit. */ + for (exponent_skippage = 0; !next_bits (1); ++exponent_skippage); + exponent_1 = (generic_floating_point_number.exponent + + generic_floating_point_number.leader + + 1 + - generic_floating_point_number.low); + + /* Radix LITTLENUM_RADIX, point just higher than + generic_floating_point_number.leader. */ exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; - /* Radix 2. */ + + /* Radix 2. */ exponent_3 = exponent_2 - exponent_skippage; - /* Forget leading zeros, forget 1st bit. */ + + /* Forget leading zeros, forget 1st bit. */ exponent_4 = exponent_3 + ((1 << (exponent_bits - 1)) - 2); - /* Offset exponent. */ + /* Offset exponent. */ lp = words; - /* Word 1. Sign, exponent and perhaps high bits. */ - word1 = (generic_floating_point_number.sign == '+') ? 0 : (1 << (LITTLENUM_NUMBER_OF_BITS - 1)); + /* Word 1. Sign, exponent and perhaps high bits. */ + word1 = ((generic_floating_point_number.sign == '+') + ? 0 + : (1 << (LITTLENUM_NUMBER_OF_BITS - 1))); - /* Assume 2's complement integers. */ - if (exponent_4 < 1 && exponent_4 >= -62) + /* Assume 2's complement integers. */ + if (exponent_4 <= 0) { int prec_bits; int num_bits; unget_bits (1); num_bits = -exponent_4; - prec_bits = LITTLENUM_NUMBER_OF_BITS * precision - (exponent_bits + 1 + num_bits); + prec_bits = + LITTLENUM_NUMBER_OF_BITS * precision - (exponent_bits + 1 + num_bits); +#ifdef TC_I386 if (precision == X_PRECISION && exponent_bits == 15) - prec_bits -= LITTLENUM_NUMBER_OF_BITS + 1; + { + /* On the i386 a denormalized extended precision float is + shifted down by one, effectively decreasing the exponent + bias by one. */ + prec_bits -= 1; + num_bits += 1; + } +#endif if (num_bits >= LITTLENUM_NUMBER_OF_BITS - exponent_bits) { - /* Bigger than one littlenum */ + /* Bigger than one littlenum. */ num_bits -= (LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits; *lp++ = word1; - if (num_bits + exponent_bits + 1 >= precision * LITTLENUM_NUMBER_OF_BITS) + if (num_bits + exponent_bits + 1 + > precision * LITTLENUM_NUMBER_OF_BITS) { - /* Exponent overflow */ + /* Exponent overflow. */ make_invalid_floating_point_number (words); - return (return_value); + return return_value; } +#ifdef TC_M68K if (precision == X_PRECISION && exponent_bits == 15) - { - *lp++ = 0; - *lp++ = 0; - num_bits -= LITTLENUM_NUMBER_OF_BITS - 1; - } + *lp++ = 0; +#endif while (num_bits >= LITTLENUM_NUMBER_OF_BITS) { num_bits -= LITTLENUM_NUMBER_OF_BITS; @@ -393,32 +491,26 @@ gen_to_words (words, precision, exponent_bits) if (precision == X_PRECISION && exponent_bits == 15) { *lp++ = word1; +#ifdef TC_M68K *lp++ = 0; - if (num_bits == LITTLENUM_NUMBER_OF_BITS) - { - *lp++ = 0; - *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS - 1); - } - else if (num_bits == LITTLENUM_NUMBER_OF_BITS - 1) - *lp++ = 0; - else - *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS - 1 - num_bits); - num_bits = 0; +#endif + *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS - num_bits); } else { - word1 |= next_bits ((LITTLENUM_NUMBER_OF_BITS - 1) - (exponent_bits + num_bits)); + word1 |= next_bits ((LITTLENUM_NUMBER_OF_BITS - 1) + - (exponent_bits + num_bits)); *lp++ = word1; } } - while (lp < words + precision) + while (lp < words_end) *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS); - /* Round the mantissa up, but don't change the number */ + /* Round the mantissa up, but don't change the number. */ if (next_bits (1)) { --lp; - if (prec_bits > LITTLENUM_NUMBER_OF_BITS) + if (prec_bits >= LITTLENUM_NUMBER_OF_BITS) { int n = 0; int tmp_bits; @@ -432,7 +524,19 @@ gen_to_words (words, precision, exponent_bits) --n; tmp_bits -= LITTLENUM_NUMBER_OF_BITS; } - if (tmp_bits > LITTLENUM_NUMBER_OF_BITS || (lp[n] & mask[tmp_bits]) != mask[tmp_bits]) + if (tmp_bits > LITTLENUM_NUMBER_OF_BITS + || (lp[n] & mask[tmp_bits]) != mask[tmp_bits] + || (prec_bits != (precision * LITTLENUM_NUMBER_OF_BITS + - exponent_bits - 1) +#ifdef TC_I386 + /* An extended precision float with only the integer + bit set would be invalid. That must be converted + to the smallest normalized number. */ + && !(precision == X_PRECISION + && prec_bits == (precision * LITTLENUM_NUMBER_OF_BITS + - exponent_bits - 2)) +#endif + )) { unsigned long carry; @@ -443,24 +547,45 @@ gen_to_words (words, precision, exponent_bits) carry >>= LITTLENUM_NUMBER_OF_BITS; } } + else + { + /* This is an overflow of the denormal numbers. We + need to forget what we have produced, and instead + generate the smallest normalized number. */ + lp = words; + word1 = ((generic_floating_point_number.sign == '+') + ? 0 + : (1 << (LITTLENUM_NUMBER_OF_BITS - 1))); + word1 |= (1 + << ((LITTLENUM_NUMBER_OF_BITS - 1) + - exponent_bits)); + *lp++ = word1; +#ifdef TC_I386 + /* Set the integer bit in the extended precision format. + This cannot happen on the m68k where the mantissa + just overflows into the integer bit above. */ + if (precision == X_PRECISION) + *lp++ = 1 << (LITTLENUM_NUMBER_OF_BITS - 1); +#endif + while (lp < words_end) + *lp++ = 0; + } } - else if ((*lp & mask[prec_bits]) != mask[prec_bits]) - lp++; + else + *lp += 1; } return return_value; } - else if (exponent_4 & ~mask[exponent_bits]) + else if ((unsigned long) exponent_4 > mask[exponent_bits] + || (! TC_LARGEST_EXPONENT_IS_NORMAL (precision) + && (unsigned long) exponent_4 == mask[exponent_bits])) { - /* - * Exponent overflow. Lose immediately. - */ - - /* - * We leave return_value alone: admit we read the - * number, but return a floating exception - * because we can't encode the number. - */ + /* Exponent overflow. Lose immediately. */ + + /* We leave return_value alone: admit we read the + number, but return a floating exception + because we can't encode the number. */ make_invalid_floating_point_number (words); return return_value; } @@ -472,72 +597,72 @@ gen_to_words (words, precision, exponent_bits) *lp++ = word1; - /* X_PRECISION is special: it has 16 bits of zero in the middle, - followed by a 1 bit. */ + /* X_PRECISION is special: on the 68k, it has 16 bits of zero in the + middle. Either way, it is then followed by a 1 bit. */ if (exponent_bits == 15 && precision == X_PRECISION) { +#ifdef TC_M68K *lp++ = 0; - *lp++ = 1 << (LITTLENUM_NUMBER_OF_BITS) | next_bits (LITTLENUM_NUMBER_OF_BITS - 1); +#endif + *lp++ = (1 << (LITTLENUM_NUMBER_OF_BITS - 1) + | next_bits (LITTLENUM_NUMBER_OF_BITS - 1)); } - /* The rest of the words are just mantissa bits. */ - while (lp < words + precision) + /* The rest of the words are just mantissa bits. */ + while (lp < words_end) *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS); if (next_bits (1)) { unsigned long carry; - /* - * Since the NEXT bit is a 1, round UP the mantissa. - * The cunning design of these hidden-1 floats permits - * us to let the mantissa overflow into the exponent, and - * it 'does the right thing'. However, we lose if the - * highest-order bit of the lowest-order word flips. - * Is that clear? - */ + /* Since the NEXT bit is a 1, round UP the mantissa. + The cunning design of these hidden-1 floats permits + us to let the mantissa overflow into the exponent, and + it 'does the right thing'. However, we lose if the + highest-order bit of the lowest-order word flips. + Is that clear? */ /* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2) - Please allow at least 1 more bit in carry than is in a LITTLENUM. - We need that extra bit to hold a carry during a LITTLENUM carry - propagation. Another extra bit (kept 0) will assure us that we - don't get a sticky sign bit after shifting right, and that - permits us to propagate the carry without any masking of bits. - #endif */ - for (carry = 1, lp--; carry && (lp >= words); lp--) + Please allow at least 1 more bit in carry than is in a LITTLENUM. + We need that extra bit to hold a carry during a LITTLENUM carry + propagation. Another extra bit (kept 0) will assure us that we + don't get a sticky sign bit after shifting right, and that + permits us to propagate the carry without any masking of bits. + #endif */ + for (carry = 1, lp--; carry; lp--) { carry = *lp + carry; *lp = carry; carry >>= LITTLENUM_NUMBER_OF_BITS; + if (lp == words) + break; + } + if (precision == X_PRECISION && exponent_bits == 15) + { + /* Extended precision numbers have an explicit integer bit + that we may have to restore. */ + if (lp == words) + { +#ifdef TC_M68K + /* On the m68k there is a gap of 16 bits. We must + explicitly propagate the carry into the exponent. */ + words[0] += words[1]; + words[1] = 0; + lp++; +#endif + /* Put back the integer bit. */ + lp[1] |= 1 << (LITTLENUM_NUMBER_OF_BITS - 1); + } } if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) { - /* We leave return_value alone: admit we read the - * number, but return a floating exception - * because we can't encode the number. - */ + /* We leave return_value alone: admit we read the number, + but return a floating exception because we can't encode + the number. */ *words &= ~(1 << (LITTLENUM_NUMBER_OF_BITS - 1)); - /* make_invalid_floating_point_number (words); */ - /* return return_value; */ } } - return (return_value); -} - -/* This routine is a real kludge. Someone really should do it better, but - I'm too lazy, and I don't understand this stuff all too well anyway - (JF) - */ -void -int_to_gen (x) - long x; -{ - char buf[20]; - char *bufp; - - sprintf (buf, "%ld", x); - bufp = &buf[0]; - if (atof_generic (&bufp, ".", EXP_CHARS, &generic_floating_point_number)) - as_bad ("Error converting number to floating point (Exponent overflow?)"); + return return_value; } #ifdef TEST @@ -564,13 +689,122 @@ print_gen (gen) sprintf (sbuf + strlen (sbuf), "%x %x %.12g\n", arr[0], arr[1], fv); if (gen) - { - generic_floating_point_number = f; - } + generic_floating_point_number = f; return (sbuf); } +#endif + +#define MAX_LITTLENUMS 6 +/* This is a utility function called from various tc-*.c files. It + is here in order to reduce code duplication. + + Turn a string at input_line_pointer into a floating point constant + of type TYPE (a character found in the FLT_CHARS macro), and store + it as LITTLENUMS in the bytes buffer LITP. The number of chars + emitted is stored in *SIZEP. BIG_WORDIAN is TRUE if the littlenums + should be emitted most significant littlenum first. + + An error message is returned, or a NULL pointer if everything went OK. */ + +const char * +ieee_md_atof (int type, + char *litP, + int *sizeP, + bfd_boolean big_wordian) +{ + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + LITTLENUM_TYPE *wordP; + char *t; + int prec = 0; + + if (strchr (FLT_CHARS, type) != NULL) + { + switch (type) + { + case 'f': + case 'F': + case 's': + case 'S': + prec = F_PRECISION; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + prec = D_PRECISION; + break; + + case 't': + case 'T': + prec = X_PRECISION; + type = 'x'; /* This is what atof_ieee() understands. */ + break; + + case 'x': + case 'X': + case 'p': + case 'P': +#ifdef TC_M68K + /* Note: on the m68k there is a gap of 16 bits (one littlenum) + between the exponent and mantissa. Hence the precision is + 6 and not 5. */ + prec = P_PRECISION + 1; +#else + prec = P_PRECISION; #endif + break; + + default: + break; + } + } + /* The 'f' and 'd' types are always recognised, even if the target has + not put them into the FLT_CHARS macro. This is because the 'f' type + can come from the .dc.s, .dcb.s, .float or .single pseudo-ops and the + 'd' type from the .dc.d, .dbc.d or .double pseudo-ops. + + The 'x' type is not implicitly recongised however, even though it can + be generated by the .dc.x and .dbc.x pseudo-ops because not all targets + can support floating point values that big. ie the target has to + explicitly allow them by putting them into FLT_CHARS. */ + else if (type == 'f') + prec = F_PRECISION; + else if (type == 'd') + prec = D_PRECISION; + + if (prec == 0) + { + *sizeP = 0; + return _("Unrecognized or unsupported floating point constant"); + } + + gas_assert (prec <= MAX_LITTLENUMS); -/* end of atof-ieee.c */ + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + + *sizeP = prec * sizeof (LITTLENUM_TYPE); + + if (big_wordian) + { + for (wordP = words; prec --;) + { + md_number_to_chars (litP, (valueT) (* wordP ++), sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); + } + } + else + { + for (wordP = words + prec; prec --;) + { + md_number_to_chars (litP, (valueT) (* -- wordP), sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); + } + } + + return NULL; +}