atof-ieee.c revision 77298
133965Sjdp/* atof_ieee.c - turn a Flonum into an IEEE floating point number 260484Sobrien Copyright (C) 1987, 92, 93, 94, 95, 96, 97, 98, 99, 2000 338889Sjdp Free Software Foundation, Inc. 433965Sjdp 533965Sjdp This file is part of GAS, the GNU Assembler. 633965Sjdp 733965Sjdp GAS is free software; you can redistribute it and/or modify 833965Sjdp it under the terms of the GNU General Public License as published by 933965Sjdp the Free Software Foundation; either version 2, or (at your option) 1033965Sjdp any later version. 1133965Sjdp 1233965Sjdp GAS is distributed in the hope that it will be useful, 1333965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1433965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1533965Sjdp GNU General Public License for more details. 1633965Sjdp 1733965Sjdp You should have received a copy of the GNU General Public License 1833965Sjdp along with GAS; see the file COPYING. If not, write to the Free 1933965Sjdp Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2033965Sjdp 02111-1307, USA. */ 2133965Sjdp 2233965Sjdp#include "as.h" 2333965Sjdp 2433965Sjdp/* Flonums returned here. */ 2533965Sjdpextern FLONUM_TYPE generic_floating_point_number; 2633965Sjdp 2733965Sjdpstatic int next_bits PARAMS ((int)); 2833965Sjdpstatic void unget_bits PARAMS ((int)); 2933965Sjdpstatic void make_invalid_floating_point_number PARAMS ((LITTLENUM_TYPE *)); 3033965Sjdp 3133965Sjdpextern const char EXP_CHARS[]; 3277298Sobrien/* Precision in LittleNums. */ 3333965Sjdp/* Don't count the gap in the m68k extended precision format. */ 3433965Sjdp#define MAX_PRECISION (5) 3533965Sjdp#define F_PRECISION (2) 3633965Sjdp#define D_PRECISION (4) 3733965Sjdp#define X_PRECISION (5) 3833965Sjdp#define P_PRECISION (5) 3933965Sjdp 4077298Sobrien/* Length in LittleNums of guard bits. */ 4133965Sjdp#define GUARD (2) 4233965Sjdp 4333965Sjdpstatic const unsigned long mask[] = 4433965Sjdp{ 4533965Sjdp 0x00000000, 4633965Sjdp 0x00000001, 4733965Sjdp 0x00000003, 4833965Sjdp 0x00000007, 4933965Sjdp 0x0000000f, 5033965Sjdp 0x0000001f, 5133965Sjdp 0x0000003f, 5233965Sjdp 0x0000007f, 5333965Sjdp 0x000000ff, 5433965Sjdp 0x000001ff, 5533965Sjdp 0x000003ff, 5633965Sjdp 0x000007ff, 5733965Sjdp 0x00000fff, 5833965Sjdp 0x00001fff, 5933965Sjdp 0x00003fff, 6033965Sjdp 0x00007fff, 6133965Sjdp 0x0000ffff, 6233965Sjdp 0x0001ffff, 6333965Sjdp 0x0003ffff, 6433965Sjdp 0x0007ffff, 6533965Sjdp 0x000fffff, 6633965Sjdp 0x001fffff, 6733965Sjdp 0x003fffff, 6833965Sjdp 0x007fffff, 6933965Sjdp 0x00ffffff, 7033965Sjdp 0x01ffffff, 7133965Sjdp 0x03ffffff, 7233965Sjdp 0x07ffffff, 7333965Sjdp 0x0fffffff, 7433965Sjdp 0x1fffffff, 7533965Sjdp 0x3fffffff, 7633965Sjdp 0x7fffffff, 7733965Sjdp 0xffffffff, 7833965Sjdp}; 7933965Sjdp 8033965Sjdpstatic int bits_left_in_littlenum; 8133965Sjdpstatic int littlenums_left; 8233965Sjdpstatic LITTLENUM_TYPE *littlenum_pointer; 8333965Sjdp 8433965Sjdpstatic int 8533965Sjdpnext_bits (number_of_bits) 8633965Sjdp int number_of_bits; 8733965Sjdp{ 8833965Sjdp int return_value; 8933965Sjdp 9033965Sjdp if (!littlenums_left) 9133965Sjdp return (0); 9233965Sjdp if (number_of_bits >= bits_left_in_littlenum) 9333965Sjdp { 9433965Sjdp return_value = mask[bits_left_in_littlenum] & *littlenum_pointer; 9533965Sjdp number_of_bits -= bits_left_in_littlenum; 9633965Sjdp return_value <<= number_of_bits; 9733965Sjdp 9833965Sjdp if (--littlenums_left) 9933965Sjdp { 10033965Sjdp bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits; 10133965Sjdp --littlenum_pointer; 10277298Sobrien return_value |= 10377298Sobrien (*littlenum_pointer >> bits_left_in_littlenum) 10477298Sobrien & mask[number_of_bits]; 10533965Sjdp } 10633965Sjdp } 10733965Sjdp else 10833965Sjdp { 10933965Sjdp bits_left_in_littlenum -= number_of_bits; 11077298Sobrien return_value = 11177298Sobrien mask[number_of_bits] & (*littlenum_pointer >> bits_left_in_littlenum); 11233965Sjdp } 11377298Sobrien return return_value; 11433965Sjdp} 11533965Sjdp 11677298Sobrien/* Num had better be less than LITTLENUM_NUMBER_OF_BITS. */ 11777298Sobrien 11833965Sjdpstatic void 11933965Sjdpunget_bits (num) 12033965Sjdp int num; 12133965Sjdp{ 12233965Sjdp if (!littlenums_left) 12333965Sjdp { 12433965Sjdp ++littlenum_pointer; 12533965Sjdp ++littlenums_left; 12633965Sjdp bits_left_in_littlenum = num; 12733965Sjdp } 12833965Sjdp else if (bits_left_in_littlenum + num > LITTLENUM_NUMBER_OF_BITS) 12933965Sjdp { 13077298Sobrien bits_left_in_littlenum = 13177298Sobrien num - (LITTLENUM_NUMBER_OF_BITS - bits_left_in_littlenum); 13233965Sjdp ++littlenum_pointer; 13333965Sjdp ++littlenums_left; 13433965Sjdp } 13533965Sjdp else 13633965Sjdp bits_left_in_littlenum += num; 13733965Sjdp} 13833965Sjdp 13933965Sjdpstatic void 14033965Sjdpmake_invalid_floating_point_number (words) 14133965Sjdp LITTLENUM_TYPE *words; 14233965Sjdp{ 14360484Sobrien as_bad (_("cannot create floating-point number")); 14477298Sobrien /* Zero the leftmost bit. */ 14577298Sobrien words[0] = (LITTLENUM_TYPE) ((unsigned) -1) >> 1; 14633965Sjdp words[1] = (LITTLENUM_TYPE) -1; 14733965Sjdp words[2] = (LITTLENUM_TYPE) -1; 14833965Sjdp words[3] = (LITTLENUM_TYPE) -1; 14933965Sjdp words[4] = (LITTLENUM_TYPE) -1; 15033965Sjdp words[5] = (LITTLENUM_TYPE) -1; 15133965Sjdp} 15233965Sjdp 15377298Sobrien/* Warning: This returns 16-bit LITTLENUMs. It is up to the caller to 15477298Sobrien figure out any alignment problems and to conspire for the 15577298Sobrien bytes/word to be emitted in the right order. Bigendians beware! */ 15633965Sjdp 15733965Sjdp/* Note that atof-ieee always has X and P precisions enabled. it is up 15833965Sjdp to md_atof to filter them out if the target machine does not support 15933965Sjdp them. */ 16033965Sjdp 16177298Sobrien/* Returns pointer past text consumed. */ 16277298Sobrien 16333965Sjdpchar * 16433965Sjdpatof_ieee (str, what_kind, words) 16577298Sobrien char *str; /* Text to convert to binary. */ 16677298Sobrien int what_kind; /* 'd', 'f', 'g', 'h'. */ 16777298Sobrien LITTLENUM_TYPE *words; /* Build the binary here. */ 16833965Sjdp{ 16977298Sobrien /* Extra bits for zeroed low-order bits. 17077298Sobrien The 1st MAX_PRECISION are zeroed, the last contain flonum bits. */ 17133965Sjdp static LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD]; 17233965Sjdp char *return_value; 17377298Sobrien /* Number of 16-bit words in the format. */ 17433965Sjdp int precision; 17533965Sjdp long exponent_bits; 17633965Sjdp FLONUM_TYPE save_gen_flonum; 17733965Sjdp 17833965Sjdp /* We have to save the generic_floating_point_number because it 17933965Sjdp contains storage allocation about the array of LITTLENUMs where 18033965Sjdp the value is actually stored. We will allocate our own array of 18133965Sjdp littlenums below, but have to restore the global one on exit. */ 18233965Sjdp save_gen_flonum = generic_floating_point_number; 18333965Sjdp 18433965Sjdp return_value = str; 18533965Sjdp generic_floating_point_number.low = bits + MAX_PRECISION; 18633965Sjdp generic_floating_point_number.high = NULL; 18733965Sjdp generic_floating_point_number.leader = NULL; 18833965Sjdp generic_floating_point_number.exponent = 0; 18933965Sjdp generic_floating_point_number.sign = '\0'; 19033965Sjdp 19133965Sjdp /* Use more LittleNums than seems necessary: the highest flonum may 19277298Sobrien have 15 leading 0 bits, so could be useless. */ 19333965Sjdp 19433965Sjdp memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION); 19533965Sjdp 19633965Sjdp switch (what_kind) 19733965Sjdp { 19833965Sjdp case 'f': 19933965Sjdp case 'F': 20033965Sjdp case 's': 20133965Sjdp case 'S': 20233965Sjdp precision = F_PRECISION; 20333965Sjdp exponent_bits = 8; 20433965Sjdp break; 20533965Sjdp 20633965Sjdp case 'd': 20733965Sjdp case 'D': 20833965Sjdp case 'r': 20933965Sjdp case 'R': 21033965Sjdp precision = D_PRECISION; 21133965Sjdp exponent_bits = 11; 21233965Sjdp break; 21333965Sjdp 21433965Sjdp case 'x': 21533965Sjdp case 'X': 21633965Sjdp case 'e': 21733965Sjdp case 'E': 21833965Sjdp precision = X_PRECISION; 21933965Sjdp exponent_bits = 15; 22033965Sjdp break; 22133965Sjdp 22233965Sjdp case 'p': 22333965Sjdp case 'P': 22433965Sjdp 22533965Sjdp precision = P_PRECISION; 22633965Sjdp exponent_bits = -1; 22733965Sjdp break; 22833965Sjdp 22933965Sjdp default: 23033965Sjdp make_invalid_floating_point_number (words); 23133965Sjdp return (NULL); 23233965Sjdp } 23333965Sjdp 23433965Sjdp generic_floating_point_number.high 23533965Sjdp = generic_floating_point_number.low + precision - 1 + GUARD; 23633965Sjdp 23733965Sjdp if (atof_generic (&return_value, ".", EXP_CHARS, 23833965Sjdp &generic_floating_point_number)) 23933965Sjdp { 24033965Sjdp make_invalid_floating_point_number (words); 24133965Sjdp return (NULL); 24233965Sjdp } 24333965Sjdp gen_to_words (words, precision, exponent_bits); 24433965Sjdp 24533965Sjdp /* Restore the generic_floating_point_number's storage alloc (and 24633965Sjdp everything else). */ 24733965Sjdp generic_floating_point_number = save_gen_flonum; 24833965Sjdp 24933965Sjdp return return_value; 25033965Sjdp} 25133965Sjdp 25233965Sjdp/* Turn generic_floating_point_number into a real float/double/extended. */ 25377298Sobrien 25433965Sjdpint 25533965Sjdpgen_to_words (words, precision, exponent_bits) 25633965Sjdp LITTLENUM_TYPE *words; 25733965Sjdp int precision; 25833965Sjdp long exponent_bits; 25933965Sjdp{ 26033965Sjdp int return_value = 0; 26133965Sjdp 26233965Sjdp long exponent_1; 26333965Sjdp long exponent_2; 26433965Sjdp long exponent_3; 26533965Sjdp long exponent_4; 26633965Sjdp int exponent_skippage; 26733965Sjdp LITTLENUM_TYPE word1; 26833965Sjdp LITTLENUM_TYPE *lp; 26933965Sjdp LITTLENUM_TYPE *words_end; 27033965Sjdp 27133965Sjdp words_end = words + precision; 27233965Sjdp#ifdef TC_M68K 27333965Sjdp if (precision == X_PRECISION) 27433965Sjdp /* On the m68k the extended precision format has a gap of 16 bits 27533965Sjdp between the exponent and the mantissa. */ 27633965Sjdp words_end++; 27733965Sjdp#endif 27833965Sjdp 27933965Sjdp if (generic_floating_point_number.low > generic_floating_point_number.leader) 28033965Sjdp { 28177298Sobrien /* 0.0e0 seen. */ 28233965Sjdp if (generic_floating_point_number.sign == '+') 28333965Sjdp words[0] = 0x0000; 28433965Sjdp else 28533965Sjdp words[0] = 0x8000; 28633965Sjdp memset (&words[1], '\0', 28733965Sjdp (words_end - words - 1) * sizeof (LITTLENUM_TYPE)); 28877298Sobrien return return_value; 28933965Sjdp } 29033965Sjdp 29177298Sobrien /* NaN: Do the right thing. */ 29233965Sjdp if (generic_floating_point_number.sign == 0) 29333965Sjdp { 29433965Sjdp if (precision == F_PRECISION) 29533965Sjdp { 29633965Sjdp words[0] = 0x7fff; 29733965Sjdp words[1] = 0xffff; 29833965Sjdp } 29933965Sjdp else if (precision == X_PRECISION) 30033965Sjdp { 30133965Sjdp#ifdef TC_M68K 30233965Sjdp words[0] = 0x7fff; 30333965Sjdp words[1] = 0; 30433965Sjdp words[2] = 0xffff; 30533965Sjdp words[3] = 0xffff; 30633965Sjdp words[4] = 0xffff; 30733965Sjdp words[5] = 0xffff; 30877298Sobrien#else /* ! TC_M68K */ 30933965Sjdp#ifdef TC_I386 31033965Sjdp words[0] = 0xffff; 31133965Sjdp words[1] = 0xc000; 31233965Sjdp words[2] = 0; 31333965Sjdp words[3] = 0; 31433965Sjdp words[4] = 0; 31577298Sobrien#else /* ! TC_I386 */ 31633965Sjdp abort (); 31777298Sobrien#endif /* ! TC_I386 */ 31877298Sobrien#endif /* ! TC_M68K */ 31933965Sjdp } 32033965Sjdp else 32133965Sjdp { 32233965Sjdp words[0] = 0x7fff; 32333965Sjdp words[1] = 0xffff; 32433965Sjdp words[2] = 0xffff; 32533965Sjdp words[3] = 0xffff; 32633965Sjdp } 32733965Sjdp return return_value; 32833965Sjdp } 32933965Sjdp else if (generic_floating_point_number.sign == 'P') 33033965Sjdp { 33177298Sobrien /* +INF: Do the right thing. */ 33233965Sjdp if (precision == F_PRECISION) 33333965Sjdp { 33433965Sjdp words[0] = 0x7f80; 33533965Sjdp words[1] = 0; 33633965Sjdp } 33733965Sjdp else if (precision == X_PRECISION) 33833965Sjdp { 33933965Sjdp#ifdef TC_M68K 34033965Sjdp words[0] = 0x7fff; 34133965Sjdp words[1] = 0; 34233965Sjdp words[2] = 0; 34333965Sjdp words[3] = 0; 34433965Sjdp words[4] = 0; 34533965Sjdp words[5] = 0; 34677298Sobrien#else /* ! TC_M68K */ 34733965Sjdp#ifdef TC_I386 34833965Sjdp words[0] = 0x7fff; 34933965Sjdp words[1] = 0x8000; 35033965Sjdp words[2] = 0; 35133965Sjdp words[3] = 0; 35233965Sjdp words[4] = 0; 35377298Sobrien#else /* ! TC_I386 */ 35433965Sjdp abort (); 35577298Sobrien#endif /* ! TC_I386 */ 35677298Sobrien#endif /* ! TC_M68K */ 35733965Sjdp } 35833965Sjdp else 35933965Sjdp { 36033965Sjdp words[0] = 0x7ff0; 36133965Sjdp words[1] = 0; 36233965Sjdp words[2] = 0; 36333965Sjdp words[3] = 0; 36433965Sjdp } 36577298Sobrien return return_value; 36633965Sjdp } 36733965Sjdp else if (generic_floating_point_number.sign == 'N') 36833965Sjdp { 36977298Sobrien /* Negative INF. */ 37033965Sjdp if (precision == F_PRECISION) 37133965Sjdp { 37233965Sjdp words[0] = 0xff80; 37333965Sjdp words[1] = 0x0; 37433965Sjdp } 37533965Sjdp else if (precision == X_PRECISION) 37633965Sjdp { 37733965Sjdp#ifdef TC_M68K 37833965Sjdp words[0] = 0xffff; 37933965Sjdp words[1] = 0; 38033965Sjdp words[2] = 0; 38133965Sjdp words[3] = 0; 38233965Sjdp words[4] = 0; 38333965Sjdp words[5] = 0; 38477298Sobrien#else /* ! TC_M68K */ 38533965Sjdp#ifdef TC_I386 38633965Sjdp words[0] = 0xffff; 38733965Sjdp words[1] = 0x8000; 38833965Sjdp words[2] = 0; 38933965Sjdp words[3] = 0; 39033965Sjdp words[4] = 0; 39177298Sobrien#else /* ! TC_I386 */ 39233965Sjdp abort (); 39377298Sobrien#endif /* ! TC_I386 */ 39477298Sobrien#endif /* ! TC_M68K */ 39533965Sjdp } 39633965Sjdp else 39733965Sjdp { 39833965Sjdp words[0] = 0xfff0; 39933965Sjdp words[1] = 0x0; 40033965Sjdp words[2] = 0x0; 40133965Sjdp words[3] = 0x0; 40233965Sjdp } 40377298Sobrien return return_value; 40433965Sjdp } 40577298Sobrien 40677298Sobrien /* The floating point formats we support have: 40777298Sobrien Bit 15 is sign bit. 40877298Sobrien Bits 14:n are excess-whatever exponent. 40977298Sobrien Bits n-1:0 (if any) are most significant bits of fraction. 41077298Sobrien Bits 15:0 of the next word(s) are the next most significant bits. 41177298Sobrien 41277298Sobrien So we need: number of bits of exponent, number of bits of 41377298Sobrien mantissa. */ 41433965Sjdp bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; 41533965Sjdp littlenum_pointer = generic_floating_point_number.leader; 41633965Sjdp littlenums_left = (1 41733965Sjdp + generic_floating_point_number.leader 41833965Sjdp - generic_floating_point_number.low); 41977298Sobrien 42077298Sobrien /* Seek (and forget) 1st significant bit. */ 42133965Sjdp for (exponent_skippage = 0; !next_bits (1); ++exponent_skippage);; 42233965Sjdp exponent_1 = (generic_floating_point_number.exponent 42333965Sjdp + generic_floating_point_number.leader 42433965Sjdp + 1 42533965Sjdp - generic_floating_point_number.low); 42677298Sobrien 42733965Sjdp /* Radix LITTLENUM_RADIX, point just higher than 42877298Sobrien generic_floating_point_number.leader. */ 42933965Sjdp exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; 43077298Sobrien 43177298Sobrien /* Radix 2. */ 43233965Sjdp exponent_3 = exponent_2 - exponent_skippage; 43377298Sobrien 43477298Sobrien /* Forget leading zeros, forget 1st bit. */ 43533965Sjdp exponent_4 = exponent_3 + ((1 << (exponent_bits - 1)) - 2); 43633965Sjdp 43777298Sobrien /* Offset exponent. */ 43833965Sjdp lp = words; 43933965Sjdp 44077298Sobrien /* Word 1. Sign, exponent and perhaps high bits. */ 44133965Sjdp word1 = ((generic_floating_point_number.sign == '+') 44233965Sjdp ? 0 44333965Sjdp : (1 << (LITTLENUM_NUMBER_OF_BITS - 1))); 44433965Sjdp 44577298Sobrien /* Assume 2's complement integers. */ 44633965Sjdp if (exponent_4 <= 0) 44733965Sjdp { 44833965Sjdp int prec_bits; 44933965Sjdp int num_bits; 45033965Sjdp 45133965Sjdp unget_bits (1); 45233965Sjdp num_bits = -exponent_4; 45377298Sobrien prec_bits = 45477298Sobrien LITTLENUM_NUMBER_OF_BITS * precision - (exponent_bits + 1 + num_bits); 45533965Sjdp#ifdef TC_I386 45633965Sjdp if (precision == X_PRECISION && exponent_bits == 15) 45733965Sjdp { 45833965Sjdp /* On the i386 a denormalized extended precision float is 45933965Sjdp shifted down by one, effectively decreasing the exponent 46033965Sjdp bias by one. */ 46133965Sjdp prec_bits -= 1; 46233965Sjdp num_bits += 1; 46333965Sjdp } 46433965Sjdp#endif 46533965Sjdp 46633965Sjdp if (num_bits >= LITTLENUM_NUMBER_OF_BITS - exponent_bits) 46733965Sjdp { 46877298Sobrien /* Bigger than one littlenum. */ 46933965Sjdp num_bits -= (LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits; 47033965Sjdp *lp++ = word1; 47177298Sobrien if (num_bits + exponent_bits + 1 47277298Sobrien > precision * LITTLENUM_NUMBER_OF_BITS) 47333965Sjdp { 47477298Sobrien /* Exponent overflow. */ 47533965Sjdp make_invalid_floating_point_number (words); 47677298Sobrien return return_value; 47733965Sjdp } 47833965Sjdp#ifdef TC_M68K 47933965Sjdp if (precision == X_PRECISION && exponent_bits == 15) 48033965Sjdp *lp++ = 0; 48133965Sjdp#endif 48233965Sjdp while (num_bits >= LITTLENUM_NUMBER_OF_BITS) 48333965Sjdp { 48433965Sjdp num_bits -= LITTLENUM_NUMBER_OF_BITS; 48533965Sjdp *lp++ = 0; 48633965Sjdp } 48733965Sjdp if (num_bits) 48833965Sjdp *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS - (num_bits)); 48933965Sjdp } 49033965Sjdp else 49133965Sjdp { 49233965Sjdp if (precision == X_PRECISION && exponent_bits == 15) 49333965Sjdp { 49433965Sjdp *lp++ = word1; 49533965Sjdp#ifdef TC_M68K 49633965Sjdp *lp++ = 0; 49733965Sjdp#endif 49833965Sjdp *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS - num_bits); 49933965Sjdp } 50033965Sjdp else 50133965Sjdp { 50277298Sobrien word1 |= next_bits ((LITTLENUM_NUMBER_OF_BITS - 1) 50377298Sobrien - (exponent_bits + num_bits)); 50433965Sjdp *lp++ = word1; 50533965Sjdp } 50633965Sjdp } 50733965Sjdp while (lp < words_end) 50833965Sjdp *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS); 50933965Sjdp 51077298Sobrien /* Round the mantissa up, but don't change the number. */ 51133965Sjdp if (next_bits (1)) 51233965Sjdp { 51333965Sjdp --lp; 51460484Sobrien if (prec_bits >= LITTLENUM_NUMBER_OF_BITS) 51533965Sjdp { 51633965Sjdp int n = 0; 51733965Sjdp int tmp_bits; 51833965Sjdp 51933965Sjdp n = 0; 52033965Sjdp tmp_bits = prec_bits; 52133965Sjdp while (tmp_bits > LITTLENUM_NUMBER_OF_BITS) 52233965Sjdp { 52333965Sjdp if (lp[n] != (LITTLENUM_TYPE) - 1) 52433965Sjdp break; 52533965Sjdp --n; 52633965Sjdp tmp_bits -= LITTLENUM_NUMBER_OF_BITS; 52733965Sjdp } 52860484Sobrien if (tmp_bits > LITTLENUM_NUMBER_OF_BITS 52960484Sobrien || (lp[n] & mask[tmp_bits]) != mask[tmp_bits] 53060484Sobrien || (prec_bits != (precision * LITTLENUM_NUMBER_OF_BITS 53160484Sobrien - exponent_bits - 1) 53260484Sobrien#ifdef TC_I386 53360484Sobrien /* An extended precision float with only the integer 53460484Sobrien bit set would be invalid. That must be converted 53560484Sobrien to the smallest normalized number. */ 53660484Sobrien && !(precision == X_PRECISION 53760484Sobrien && prec_bits == (precision * LITTLENUM_NUMBER_OF_BITS 53860484Sobrien - exponent_bits - 2)) 53960484Sobrien#endif 54060484Sobrien )) 54133965Sjdp { 54233965Sjdp unsigned long carry; 54333965Sjdp 54433965Sjdp for (carry = 1; carry && (lp >= words); lp--) 54533965Sjdp { 54633965Sjdp carry = *lp + carry; 54733965Sjdp *lp = carry; 54833965Sjdp carry >>= LITTLENUM_NUMBER_OF_BITS; 54933965Sjdp } 55033965Sjdp } 55138889Sjdp else 55238889Sjdp { 55338889Sjdp /* This is an overflow of the denormal numbers. We 55438889Sjdp need to forget what we have produced, and instead 55538889Sjdp generate the smallest normalized number. */ 55638889Sjdp lp = words; 55738889Sjdp word1 = ((generic_floating_point_number.sign == '+') 55838889Sjdp ? 0 55938889Sjdp : (1 << (LITTLENUM_NUMBER_OF_BITS - 1))); 56038889Sjdp word1 |= (1 56138889Sjdp << ((LITTLENUM_NUMBER_OF_BITS - 1) 56238889Sjdp - exponent_bits)); 56338889Sjdp *lp++ = word1; 56460484Sobrien#ifdef TC_I386 56560484Sobrien /* Set the integer bit in the extended precision format. 56660484Sobrien This cannot happen on the m68k where the mantissa 56760484Sobrien just overflows into the integer bit above. */ 56860484Sobrien if (precision == X_PRECISION) 56960484Sobrien *lp++ = 1 << (LITTLENUM_NUMBER_OF_BITS - 1); 57060484Sobrien#endif 57138889Sjdp while (lp < words_end) 57238889Sjdp *lp++ = 0; 57338889Sjdp } 57433965Sjdp } 57560484Sobrien else 57633965Sjdp *lp += 1; 57733965Sjdp } 57833965Sjdp 57933965Sjdp return return_value; 58033965Sjdp } 58138889Sjdp else if ((unsigned long) exponent_4 >= mask[exponent_bits]) 58233965Sjdp { 58377298Sobrien /* Exponent overflow. Lose immediately. */ 58433965Sjdp 58577298Sobrien /* We leave return_value alone: admit we read the 58677298Sobrien number, but return a floating exception 58777298Sobrien because we can't encode the number. */ 58833965Sjdp make_invalid_floating_point_number (words); 58933965Sjdp return return_value; 59033965Sjdp } 59133965Sjdp else 59233965Sjdp { 59333965Sjdp word1 |= (exponent_4 << ((LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits)) 59433965Sjdp | next_bits ((LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits); 59533965Sjdp } 59633965Sjdp 59733965Sjdp *lp++ = word1; 59833965Sjdp 59933965Sjdp /* X_PRECISION is special: on the 68k, it has 16 bits of zero in the 60077298Sobrien middle. Either way, it is then followed by a 1 bit. */ 60133965Sjdp if (exponent_bits == 15 && precision == X_PRECISION) 60233965Sjdp { 60333965Sjdp#ifdef TC_M68K 60433965Sjdp *lp++ = 0; 60533965Sjdp#endif 60633965Sjdp *lp++ = (1 << (LITTLENUM_NUMBER_OF_BITS - 1) 60733965Sjdp | next_bits (LITTLENUM_NUMBER_OF_BITS - 1)); 60833965Sjdp } 60933965Sjdp 61077298Sobrien /* The rest of the words are just mantissa bits. */ 61133965Sjdp while (lp < words_end) 61233965Sjdp *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS); 61333965Sjdp 61433965Sjdp if (next_bits (1)) 61533965Sjdp { 61633965Sjdp unsigned long carry; 61777298Sobrien /* Since the NEXT bit is a 1, round UP the mantissa. 61877298Sobrien The cunning design of these hidden-1 floats permits 61977298Sobrien us to let the mantissa overflow into the exponent, and 62077298Sobrien it 'does the right thing'. However, we lose if the 62177298Sobrien highest-order bit of the lowest-order word flips. 62277298Sobrien Is that clear? */ 62333965Sjdp 62433965Sjdp /* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2) 62533965Sjdp Please allow at least 1 more bit in carry than is in a LITTLENUM. 62633965Sjdp We need that extra bit to hold a carry during a LITTLENUM carry 62733965Sjdp propagation. Another extra bit (kept 0) will assure us that we 62833965Sjdp don't get a sticky sign bit after shifting right, and that 62933965Sjdp permits us to propagate the carry without any masking of bits. 63033965Sjdp #endif */ 63160484Sobrien for (carry = 1, lp--; carry; lp--) 63233965Sjdp { 63333965Sjdp carry = *lp + carry; 63433965Sjdp *lp = carry; 63533965Sjdp carry >>= LITTLENUM_NUMBER_OF_BITS; 63660484Sobrien if (lp == words) 63760484Sobrien break; 63833965Sjdp } 63933965Sjdp if (precision == X_PRECISION && exponent_bits == 15) 64033965Sjdp { 64133965Sjdp /* Extended precision numbers have an explicit integer bit 64233965Sjdp that we may have to restore. */ 64333965Sjdp if (lp == words) 64433965Sjdp { 64533965Sjdp#ifdef TC_M68K 64633965Sjdp /* On the m68k there is a gap of 16 bits. We must 64777298Sobrien explicitly propagate the carry into the exponent. */ 64833965Sjdp words[0] += words[1]; 64933965Sjdp words[1] = 0; 65033965Sjdp lp++; 65133965Sjdp#endif 65277298Sobrien /* Put back the integer bit. */ 65333965Sjdp lp[1] |= 1 << (LITTLENUM_NUMBER_OF_BITS - 1); 65433965Sjdp } 65577298Sobrien } 65633965Sjdp if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) 65733965Sjdp { 65877298Sobrien /* We leave return_value alone: admit we read the number, 65977298Sobrien but return a floating exception because we can't encode 66077298Sobrien the number. */ 66133965Sjdp *words &= ~(1 << (LITTLENUM_NUMBER_OF_BITS - 1)); 66277298Sobrien#if 0 66377298Sobrien make_invalid_floating_point_number (words); 66477298Sobrien return return_value; 66577298Sobrien#endif 66633965Sjdp } 66733965Sjdp } 66877298Sobrien return return_value; 66933965Sjdp} 67033965Sjdp 67177298Sobrien#if 0 67277298Sobrien/* Unused. */ 67333965Sjdp/* This routine is a real kludge. Someone really should do it better, 67433965Sjdp but I'm too lazy, and I don't understand this stuff all too well 67533965Sjdp anyway. (JF) */ 67677298Sobrien 67733965Sjdpstatic void 67833965Sjdpint_to_gen (x) 67933965Sjdp long x; 68033965Sjdp{ 68133965Sjdp char buf[20]; 68233965Sjdp char *bufp; 68333965Sjdp 68433965Sjdp sprintf (buf, "%ld", x); 68533965Sjdp bufp = &buf[0]; 68633965Sjdp if (atof_generic (&bufp, ".", EXP_CHARS, &generic_floating_point_number)) 68760484Sobrien as_bad (_("Error converting number to floating point (Exponent overflow?)")); 68833965Sjdp} 68933965Sjdp#endif 69033965Sjdp 69133965Sjdp#ifdef TEST 69233965Sjdpchar * 69333965Sjdpprint_gen (gen) 69433965Sjdp FLONUM_TYPE *gen; 69533965Sjdp{ 69633965Sjdp FLONUM_TYPE f; 69733965Sjdp LITTLENUM_TYPE arr[10]; 69833965Sjdp double dv; 69933965Sjdp float fv; 70033965Sjdp static char sbuf[40]; 70133965Sjdp 70233965Sjdp if (gen) 70333965Sjdp { 70433965Sjdp f = generic_floating_point_number; 70533965Sjdp generic_floating_point_number = *gen; 70633965Sjdp } 70733965Sjdp gen_to_words (&arr[0], 4, 11); 70833965Sjdp memcpy (&dv, &arr[0], sizeof (double)); 70933965Sjdp sprintf (sbuf, "%x %x %x %x %.14G ", arr[0], arr[1], arr[2], arr[3], dv); 71033965Sjdp gen_to_words (&arr[0], 2, 8); 71133965Sjdp memcpy (&fv, &arr[0], sizeof (float)); 71233965Sjdp sprintf (sbuf + strlen (sbuf), "%x %x %.12g\n", arr[0], arr[1], fv); 71333965Sjdp 71433965Sjdp if (gen) 71577298Sobrien generic_floating_point_number = f; 71633965Sjdp 71733965Sjdp return (sbuf); 71833965Sjdp} 71933965Sjdp 72033965Sjdp#endif 721