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 1, 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. */
168 generic_floating_point_number
.low
= bits
+ MAX_PRECISION
;
169 generic_floating_point_number
.high
= NULL
;
170 generic_floating_point_number
.leader
= NULL
;
171 generic_floating_point_number
.exponent
= NULL
;
172 generic_floating_point_number
.sign
= '\0';
174 /* Use more LittleNums than seems */
175 /* necessary: the highest flonum may have */
176 /* 15 leading 0 bits, so could be useless. */
178 bzero (bits
, sizeof(LITTLENUM_TYPE
) * MAX_PRECISION
);
185 precision
= F_PRECISION
;
193 precision
= D_PRECISION
;
201 precision
= X_PRECISION
;
208 precision
= P_PRECISION
;
213 make_invalid_floating_point_number (words
);
217 generic_floating_point_number
.high
= generic_floating_point_number
.low
+ precision
- 1 + GUARD
;
219 if (atof_generic (& return_value
, ".", EXP_CHARS
, & generic_floating_point_number
)) {
220 /* as_bad("Error converting floating point number (Exponent overflow?)"); */
221 make_invalid_floating_point_number (words
);
224 gen_to_words(words
, precision
, exponent_bits
);
228 /* Turn generic_floating_point_number into a real float/double/extended */
229 int gen_to_words(words
, precision
, exponent_bits
)
230 LITTLENUM_TYPE
*words
;
240 int exponent_skippage
;
241 LITTLENUM_TYPE word1
;
244 if (generic_floating_point_number
.low
> generic_floating_point_number
.leader
) {
246 if(generic_floating_point_number
.sign
=='+')
250 bzero (&words
[1], sizeof(LITTLENUM_TYPE
) * (precision
-1));
254 /* NaN: Do the right thing */
255 if(generic_floating_point_number
.sign
==0) {
256 if(precision
==F_PRECISION
) {
266 } else if(generic_floating_point_number
.sign
=='P') {
267 /* +INF: Do the right thing */
268 if(precision
==F_PRECISION
) {
278 } else if(generic_floating_point_number
.sign
=='N') {
280 if(precision
==F_PRECISION
) {
292 * The floating point formats we support have:
293 * Bit 15 is sign bit.
294 * Bits 14:n are excess-whatever exponent.
295 * Bits n-1:0 (if any) are most significant bits of fraction.
296 * Bits 15:0 of the next word(s) are the next most significant bits.
298 * So we need: number of bits of exponent, number of bits of
301 bits_left_in_littlenum
= LITTLENUM_NUMBER_OF_BITS
;
302 littlenum_pointer
= generic_floating_point_number
.leader
;
303 littlenums_left
= 1+generic_floating_point_number
.leader
- generic_floating_point_number
.low
;
304 /* Seek (and forget) 1st significant bit */
305 for (exponent_skippage
= 0;! next_bits(1); exponent_skippage
++)
307 exponent_1
= generic_floating_point_number
.exponent
+ generic_floating_point_number
.leader
+ 1 -
308 generic_floating_point_number
.low
;
309 /* Radix LITTLENUM_RADIX, point just higher than generic_floating_point_number.leader. */
310 exponent_2
= exponent_1
* LITTLENUM_NUMBER_OF_BITS
;
312 exponent_3
= exponent_2
- exponent_skippage
;
313 /* Forget leading zeros, forget 1st bit. */
314 exponent_4
= exponent_3
+ ((1 << (exponent_bits
- 1)) - 2);
315 /* Offset exponent. */
319 /* Word 1. Sign, exponent and perhaps high bits. */
320 word1
= (generic_floating_point_number
.sign
== '+') ? 0 : (1<<(LITTLENUM_NUMBER_OF_BITS
-1));
322 /* Assume 2's complement integers. */
323 if(exponent_4
<1 && exponent_4
>=-62) {
328 num_bits
= -exponent_4
;
329 prec_bits
=LITTLENUM_NUMBER_OF_BITS
*precision
-(exponent_bits
+1+num_bits
);
330 if(precision
==X_PRECISION
&& exponent_bits
==15)
331 prec_bits
-=LITTLENUM_NUMBER_OF_BITS
+1;
333 if(num_bits
>=LITTLENUM_NUMBER_OF_BITS
-exponent_bits
) {
334 /* Bigger than one littlenum */
335 num_bits
-=(LITTLENUM_NUMBER_OF_BITS
-1)-exponent_bits
;
337 if(num_bits
+exponent_bits
+1>=precision
*LITTLENUM_NUMBER_OF_BITS
) {
338 /* Exponent overflow */
339 make_invalid_floating_point_number(words
);
342 if(precision
==X_PRECISION
&& exponent_bits
==15) {
345 num_bits
-=LITTLENUM_NUMBER_OF_BITS
-1;
347 while(num_bits
>=LITTLENUM_NUMBER_OF_BITS
) {
348 num_bits
-=LITTLENUM_NUMBER_OF_BITS
;
352 *lp
++=next_bits(LITTLENUM_NUMBER_OF_BITS
-(num_bits
));
354 if(precision
==X_PRECISION
&& exponent_bits
==15) {
357 if(num_bits
==LITTLENUM_NUMBER_OF_BITS
) {
359 *lp
++=next_bits(LITTLENUM_NUMBER_OF_BITS
-1);
360 } else if(num_bits
==LITTLENUM_NUMBER_OF_BITS
-1)
363 *lp
++=next_bits(LITTLENUM_NUMBER_OF_BITS
-1-num_bits
);
366 word1
|= next_bits ((LITTLENUM_NUMBER_OF_BITS
-1) - (exponent_bits
+num_bits
));
370 while(lp
<words
+precision
)
371 *lp
++=next_bits(LITTLENUM_NUMBER_OF_BITS
);
373 /* Round the mantissa up, but don't change the number */
376 if(prec_bits
>LITTLENUM_NUMBER_OF_BITS
) {
382 while(tmp_bits
>LITTLENUM_NUMBER_OF_BITS
) {
383 if(lp
[n
]!=(LITTLENUM_TYPE
)-1)
386 tmp_bits
-=LITTLENUM_NUMBER_OF_BITS
;
388 if(tmp_bits
>LITTLENUM_NUMBER_OF_BITS
|| (lp
[n
]&mask
[tmp_bits
])!=mask
[tmp_bits
]) {
391 for (carry
= 1; carry
&& (lp
>= words
); lp
--) {
392 carry
= * lp
+ carry
;
394 carry
>>= LITTLENUM_NUMBER_OF_BITS
;
397 } else if((*lp
&mask
[prec_bits
])!=mask
[prec_bits
])
402 } else if (exponent_4
& ~ mask
[exponent_bits
]) {
404 * Exponent overflow. Lose immediately.
408 * We leave return_value alone: admit we read the
409 * number, but return a floating exception
410 * because we can't encode the number.
412 make_invalid_floating_point_number (words
);
415 word1
|= (exponent_4
<< ((LITTLENUM_NUMBER_OF_BITS
-1) - exponent_bits
))
416 | next_bits ((LITTLENUM_NUMBER_OF_BITS
-1) - exponent_bits
);
421 /* X_PRECISION is special: it has 16 bits of zero in the middle,
422 followed by a 1 bit. */
423 if(exponent_bits
==15 && precision
==X_PRECISION
) {
425 *lp
++= 1<<(LITTLENUM_NUMBER_OF_BITS
)|next_bits(LITTLENUM_NUMBER_OF_BITS
-1);
428 /* The rest of the words are just mantissa bits. */
429 while(lp
< words
+ precision
)
430 *lp
++ = next_bits (LITTLENUM_NUMBER_OF_BITS
);
435 * Since the NEXT bit is a 1, round UP the mantissa.
436 * The cunning design of these hidden-1 floats permits
437 * us to let the mantissa overflow into the exponent, and
438 * it 'does the right thing'. However, we lose if the
439 * highest-order bit of the lowest-order word flips.
444 /* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2)
445 Please allow at least 1 more bit in carry than is in a LITTLENUM.
446 We need that extra bit to hold a carry during a LITTLENUM carry
447 propagation. Another extra bit (kept 0) will assure us that we
448 don't get a sticky sign bit after shifting right, and that
449 permits us to propagate the carry without any masking of bits.
451 for (carry
= 1, lp
--; carry
&& (lp
>= words
); lp
--) {
452 carry
= * lp
+ carry
;
454 carry
>>= LITTLENUM_NUMBER_OF_BITS
;
456 if ( (word1
^ *words
) & (1 << (LITTLENUM_NUMBER_OF_BITS
- 1)) ) {
457 /* We leave return_value alone: admit we read the
458 * number, but return a floating exception
459 * because we can't encode the number.
461 *words
&= ~ (1 << (LITTLENUM_NUMBER_OF_BITS
- 1));
462 /* make_invalid_floating_point_number (words); */
463 /* return return_value; */
466 return (return_value
);
469 /* This routine is a real kludge. Someone really should do it better, but
470 I'm too lazy, and I don't understand this stuff all too well anyway
480 sprintf(buf
,"%ld",x
);
482 if(atof_generic(&bufp
,".", EXP_CHARS
, &generic_floating_point_number
))
483 as_bad("Error converting number to floating point (Exponent overflow?)");
492 LITTLENUM_TYPE arr
[10];
495 static char sbuf
[40];
498 f
=generic_floating_point_number
;
499 generic_floating_point_number
= *gen
;
501 gen_to_words(&arr
[0],4,11);
502 bcopy(&arr
[0],&dv
,sizeof(double));
503 sprintf(sbuf
,"%x %x %x %x %.14G ",arr
[0],arr
[1],arr
[2],arr
[3],dv
);
504 gen_to_words(&arr
[0],2,8);
505 bcopy(&arr
[0],&fv
,sizeof(float));
506 sprintf(sbuf
+strlen(sbuf
),"%x %x %.12g\n",arr
[0],arr
[1],fv
);
508 generic_floating_point_number
=f
;