1 /* atof_ieee.c - turn a Flonum into an IEEE floating point number
2 Copyright (C) 1987 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS 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, or (at your option)
11 GAS 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.
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
23 #define bzero(s,n) memset(s,0,n)
24 #define bcopy(from,to,n) memcpy((to),(from),(n))
27 extern FLONUM_TYPE generic_floating_point_number
; /* Flonums returned here. */
33 extern char EXP_CHARS
[];
34 /* Precision in LittleNums. */
35 #define MAX_PRECISION (6)
36 #define F_PRECISION (2)
37 #define D_PRECISION (4)
38 #define X_PRECISION (6)
39 #define P_PRECISION (6)
41 /* Length in LittleNums of guard bits. */
44 static unsigned long mask
[] = {
81 static int bits_left_in_littlenum
;
82 static int littlenums_left
;
83 static LITTLENUM_TYPE
*littlenum_pointer
;
86 next_bits (number_of_bits
)
93 if (number_of_bits
>= bits_left_in_littlenum
)
95 return_value
= mask
[bits_left_in_littlenum
] & *littlenum_pointer
;
96 number_of_bits
-= bits_left_in_littlenum
;
97 return_value
<<= number_of_bits
;
98 if(--littlenums_left
) {
99 bits_left_in_littlenum
= LITTLENUM_NUMBER_OF_BITS
- number_of_bits
;
100 littlenum_pointer
--;
101 return_value
|= (*littlenum_pointer
>>bits_left_in_littlenum
) & mask
[number_of_bits
];
106 bits_left_in_littlenum
-= number_of_bits
;
107 return_value
= mask
[number_of_bits
] & (*littlenum_pointer
>>bits_left_in_littlenum
);
109 return (return_value
);
112 /* Num had better be less than LITTLENUM_NUMBER_OF_BITS */
117 if(!littlenums_left
) {
120 bits_left_in_littlenum
=num
;
121 } else if(bits_left_in_littlenum
+num
>LITTLENUM_NUMBER_OF_BITS
) {
122 bits_left_in_littlenum
= num
-(LITTLENUM_NUMBER_OF_BITS
-bits_left_in_littlenum
);
126 bits_left_in_littlenum
+=num
;
130 make_invalid_floating_point_number (words
)
131 LITTLENUM_TYPE
* words
;
133 as_bad("cannot create floating-point number");
134 words
[0]= ((unsigned)-1)>>1; /* Zero the leftmost bit */
142 /***********************************************************************\
143 * Warning: this returns 16-bit LITTLENUMs. It is up to the caller *
144 * to figure out any alignment problems and to conspire for the *
145 * bytes/word to be emitted in the right order. Bigendians beware! *
147 \***********************************************************************/
149 /* Note that atof-ieee always has X and P precisions enabled. it is up
150 to md_atof to filter them out if the target machine does not support
153 char * /* Return pointer past text consumed. */
154 atof_ieee (str
, what_kind
, words
)
155 char * str
; /* Text to convert to binary. */
156 char what_kind
; /* 'd', 'f', 'g', 'h' */
157 LITTLENUM_TYPE
* words
; /* Build the binary here. */
159 static LITTLENUM_TYPE bits
[MAX_PRECISION
+ MAX_PRECISION
+ GUARD
];
160 /* Extra bits for zeroed low-order bits. */
161 /* The 1st MAX_PRECISION are zeroed, */
162 /* the last contain flonum bits. */
164 int precision
; /* Number of 16-bit words in the format. */
166 FLONUM_TYPE save_gen_flonum
;
168 /* We have to save the generic_floating_point_number because it
169 contains storage allocation about the array of LITTLENUMs
170 where the value is actually stored. We will allocate our
171 own array of littlenums below, but have to restore the global
173 save_gen_flonum
= generic_floating_point_number
;
176 generic_floating_point_number
.low
= bits
+ MAX_PRECISION
;
177 generic_floating_point_number
.high
= NULL
;
178 generic_floating_point_number
.leader
= NULL
;
179 generic_floating_point_number
.exponent
= NULL
;
180 generic_floating_point_number
.sign
= '\0';
182 /* Use more LittleNums than seems */
183 /* necessary: the highest flonum may have */
184 /* 15 leading 0 bits, so could be useless. */
186 bzero (bits
, sizeof(LITTLENUM_TYPE
) * MAX_PRECISION
);
193 precision
= F_PRECISION
;
201 precision
= D_PRECISION
;
209 precision
= X_PRECISION
;
216 precision
= P_PRECISION
;
221 make_invalid_floating_point_number (words
);
225 generic_floating_point_number
.high
= generic_floating_point_number
.low
+ precision
- 1 + GUARD
;
227 if (atof_generic (& return_value
, ".", EXP_CHARS
, & generic_floating_point_number
)) {
228 /* as_bad("Error converting floating point number (Exponent overflow?)"); */
229 make_invalid_floating_point_number (words
);
232 gen_to_words(words
, precision
, exponent_bits
);
234 /* Restore the generic_floating_point_number's storage alloc
235 (and everything else). */
236 generic_floating_point_number
= save_gen_flonum
;
241 /* Turn generic_floating_point_number into a real float/double/extended */
242 int gen_to_words(words
, precision
, exponent_bits
)
243 LITTLENUM_TYPE
*words
;
253 int exponent_skippage
;
254 LITTLENUM_TYPE word1
;
257 if (generic_floating_point_number
.low
> generic_floating_point_number
.leader
) {
259 if(generic_floating_point_number
.sign
=='+')
263 bzero (&words
[1], sizeof(LITTLENUM_TYPE
) * (precision
-1));
267 /* NaN: Do the right thing */
268 if(generic_floating_point_number
.sign
==0) {
269 if(precision
==F_PRECISION
) {
279 } else if(generic_floating_point_number
.sign
=='P') {
280 /* +INF: Do the right thing */
281 if(precision
==F_PRECISION
) {
291 } else if(generic_floating_point_number
.sign
=='N') {
293 if(precision
==F_PRECISION
) {
305 * The floating point formats we support have:
306 * Bit 15 is sign bit.
307 * Bits 14:n are excess-whatever exponent.
308 * Bits n-1:0 (if any) are most significant bits of fraction.
309 * Bits 15:0 of the next word(s) are the next most significant bits.
311 * So we need: number of bits of exponent, number of bits of
314 bits_left_in_littlenum
= LITTLENUM_NUMBER_OF_BITS
;
315 littlenum_pointer
= generic_floating_point_number
.leader
;
316 littlenums_left
= 1+generic_floating_point_number
.leader
- generic_floating_point_number
.low
;
317 /* Seek (and forget) 1st significant bit */
318 for (exponent_skippage
= 0;! next_bits(1); exponent_skippage
++)
320 exponent_1
= generic_floating_point_number
.exponent
+ generic_floating_point_number
.leader
+ 1 -
321 generic_floating_point_number
.low
;
322 /* Radix LITTLENUM_RADIX, point just higher than generic_floating_point_number.leader. */
323 exponent_2
= exponent_1
* LITTLENUM_NUMBER_OF_BITS
;
325 exponent_3
= exponent_2
- exponent_skippage
;
326 /* Forget leading zeros, forget 1st bit. */
327 exponent_4
= exponent_3
+ ((1 << (exponent_bits
- 1)) - 2);
328 /* Offset exponent. */
332 /* Word 1. Sign, exponent and perhaps high bits. */
333 word1
= (generic_floating_point_number
.sign
== '+') ? 0 : (1<<(LITTLENUM_NUMBER_OF_BITS
-1));
335 /* Assume 2's complement integers. */
336 if(exponent_4
<1 && exponent_4
>=-62) {
341 num_bits
= -exponent_4
;
342 prec_bits
=LITTLENUM_NUMBER_OF_BITS
*precision
-(exponent_bits
+1+num_bits
);
343 if(precision
==X_PRECISION
&& exponent_bits
==15)
344 prec_bits
-=LITTLENUM_NUMBER_OF_BITS
+1;
346 if(num_bits
>=LITTLENUM_NUMBER_OF_BITS
-exponent_bits
) {
347 /* Bigger than one littlenum */
348 num_bits
-=(LITTLENUM_NUMBER_OF_BITS
-1)-exponent_bits
;
350 if(num_bits
+exponent_bits
+1>=precision
*LITTLENUM_NUMBER_OF_BITS
) {
351 /* Exponent overflow */
352 make_invalid_floating_point_number(words
);
355 if(precision
==X_PRECISION
&& exponent_bits
==15) {
358 num_bits
-=LITTLENUM_NUMBER_OF_BITS
-1;
360 while(num_bits
>=LITTLENUM_NUMBER_OF_BITS
) {
361 num_bits
-=LITTLENUM_NUMBER_OF_BITS
;
365 *lp
++=next_bits(LITTLENUM_NUMBER_OF_BITS
-(num_bits
));
367 if(precision
==X_PRECISION
&& exponent_bits
==15) {
370 if(num_bits
==LITTLENUM_NUMBER_OF_BITS
) {
372 *lp
++=next_bits(LITTLENUM_NUMBER_OF_BITS
-1);
373 } else if(num_bits
==LITTLENUM_NUMBER_OF_BITS
-1)
376 *lp
++=next_bits(LITTLENUM_NUMBER_OF_BITS
-1-num_bits
);
379 word1
|= next_bits ((LITTLENUM_NUMBER_OF_BITS
-1) - (exponent_bits
+num_bits
));
383 while(lp
<words
+precision
)
384 *lp
++=next_bits(LITTLENUM_NUMBER_OF_BITS
);
386 /* Round the mantissa up, but don't change the number */
389 if(prec_bits
>LITTLENUM_NUMBER_OF_BITS
) {
395 while(tmp_bits
>LITTLENUM_NUMBER_OF_BITS
) {
396 if(lp
[n
]!=(LITTLENUM_TYPE
)-1)
399 tmp_bits
-=LITTLENUM_NUMBER_OF_BITS
;
401 if(tmp_bits
>LITTLENUM_NUMBER_OF_BITS
|| (lp
[n
]&mask
[tmp_bits
])!=mask
[tmp_bits
]) {
404 for (carry
= 1; carry
&& (lp
>= words
); lp
--) {
405 carry
= * lp
+ carry
;
407 carry
>>= LITTLENUM_NUMBER_OF_BITS
;
410 } else if((*lp
&mask
[prec_bits
])!=mask
[prec_bits
])
415 } else if (exponent_4
& ~ mask
[exponent_bits
]) {
417 * Exponent overflow. Lose immediately.
421 * We leave return_value alone: admit we read the
422 * number, but return a floating exception
423 * because we can't encode the number.
425 make_invalid_floating_point_number (words
);
428 word1
|= (exponent_4
<< ((LITTLENUM_NUMBER_OF_BITS
-1) - exponent_bits
))
429 | next_bits ((LITTLENUM_NUMBER_OF_BITS
-1) - exponent_bits
);
434 /* X_PRECISION is special: it has 16 bits of zero in the middle,
435 followed by a 1 bit. */
436 if(exponent_bits
==15 && precision
==X_PRECISION
) {
438 *lp
++= 1<<(LITTLENUM_NUMBER_OF_BITS
)|next_bits(LITTLENUM_NUMBER_OF_BITS
-1);
441 /* The rest of the words are just mantissa bits. */
442 while(lp
< words
+ precision
)
443 *lp
++ = next_bits (LITTLENUM_NUMBER_OF_BITS
);
448 * Since the NEXT bit is a 1, round UP the mantissa.
449 * The cunning design of these hidden-1 floats permits
450 * us to let the mantissa overflow into the exponent, and
451 * it 'does the right thing'. However, we lose if the
452 * highest-order bit of the lowest-order word flips.
457 /* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2)
458 Please allow at least 1 more bit in carry than is in a LITTLENUM.
459 We need that extra bit to hold a carry during a LITTLENUM carry
460 propagation. Another extra bit (kept 0) will assure us that we
461 don't get a sticky sign bit after shifting right, and that
462 permits us to propagate the carry without any masking of bits.
464 for (carry
= 1, lp
--; carry
&& (lp
>= words
); lp
--) {
465 carry
= * lp
+ carry
;
467 carry
>>= LITTLENUM_NUMBER_OF_BITS
;
469 if ( (word1
^ *words
) & (1 << (LITTLENUM_NUMBER_OF_BITS
- 1)) ) {
470 /* We leave return_value alone: admit we read the
471 * number, but return a floating exception
472 * because we can't encode the number.
474 *words
&= ~ (1 << (LITTLENUM_NUMBER_OF_BITS
- 1));
475 /* make_invalid_floating_point_number (words); */
476 /* return return_value; */
479 return (return_value
);
482 /* This routine is a real kludge. Someone really should do it better, but
483 I'm too lazy, and I don't understand this stuff all too well anyway
493 sprintf(buf
,"%ld",x
);
495 if(atof_generic(&bufp
,".", EXP_CHARS
, &generic_floating_point_number
))
496 as_bad("Error converting number to floating point (Exponent overflow?)");
505 LITTLENUM_TYPE arr
[10];
508 static char sbuf
[40];
511 f
=generic_floating_point_number
;
512 generic_floating_point_number
= *gen
;
514 gen_to_words(&arr
[0],4,11);
515 bcopy(&arr
[0],&dv
,sizeof(double));
516 sprintf(sbuf
,"%x %x %x %x %.14G ",arr
[0],arr
[1],arr
[2],arr
[3],dv
);
517 gen_to_words(&arr
[0],2,8);
518 bcopy(&arr
[0],&fv
,sizeof(float));
519 sprintf(sbuf
+strlen(sbuf
),"%x %x %.12g\n",arr
[0],arr
[1],fv
);
521 generic_floating_point_number
=f
;
526 /* end of atof-ieee.c */