1 /* atof_ieee.c - turn a Flonum into an IEEE floating point number
2    Copyright 1987, 1992, 1994, 1996, 1997, 1998, 1999, 2000, 2001
3    Free Software Foundation, Inc.
4 
5    This file is part of GAS, the GNU Assembler.
6 
7    GAS is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2, or (at your option)
10    any later version.
11 
12    GAS is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with GAS; see the file COPYING.  If not, write to the Free
19    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA.  */
21 
22 #include "as.h"
23 
24 /* Flonums returned here.  */
25 extern FLONUM_TYPE generic_floating_point_number;
26 
27 static int next_bits PARAMS ((int));
28 static void unget_bits PARAMS ((int));
29 static void make_invalid_floating_point_number PARAMS ((LITTLENUM_TYPE *));
30 
31 extern const char EXP_CHARS[];
32 /* Precision in LittleNums.  */
33 /* Don't count the gap in the m68k extended precision format.  */
34 #define MAX_PRECISION (5)
35 #define F_PRECISION (2)
36 #define D_PRECISION (4)
37 #define X_PRECISION (5)
38 #define P_PRECISION (5)
39 
40 /* Length in LittleNums of guard bits.  */
41 #define GUARD (2)
42 
43 #ifndef TC_LARGEST_EXPONENT_IS_NORMAL
44 #define TC_LARGEST_EXPONENT_IS_NORMAL(PRECISION) 0
45 #endif
46 
47 static const unsigned long mask[] =
48 {
49   0x00000000,
50   0x00000001,
51   0x00000003,
52   0x00000007,
53   0x0000000f,
54   0x0000001f,
55   0x0000003f,
56   0x0000007f,
57   0x000000ff,
58   0x000001ff,
59   0x000003ff,
60   0x000007ff,
61   0x00000fff,
62   0x00001fff,
63   0x00003fff,
64   0x00007fff,
65   0x0000ffff,
66   0x0001ffff,
67   0x0003ffff,
68   0x0007ffff,
69   0x000fffff,
70   0x001fffff,
71   0x003fffff,
72   0x007fffff,
73   0x00ffffff,
74   0x01ffffff,
75   0x03ffffff,
76   0x07ffffff,
77   0x0fffffff,
78   0x1fffffff,
79   0x3fffffff,
80   0x7fffffff,
81   0xffffffff,
82 };
83 
84 static int bits_left_in_littlenum;
85 static int littlenums_left;
86 static LITTLENUM_TYPE *littlenum_pointer;
87 
88 static int
next_bits(number_of_bits)89 next_bits (number_of_bits)
90      int number_of_bits;
91 {
92   int return_value;
93 
94   if (!littlenums_left)
95     return (0);
96   if (number_of_bits >= bits_left_in_littlenum)
97     {
98       return_value = mask[bits_left_in_littlenum] & *littlenum_pointer;
99       number_of_bits -= bits_left_in_littlenum;
100       return_value <<= number_of_bits;
101 
102       if (--littlenums_left)
103 	{
104 	  bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits;
105 	  --littlenum_pointer;
106 	  return_value |=
107 	    (*littlenum_pointer >> bits_left_in_littlenum)
108 	    & mask[number_of_bits];
109 	}
110     }
111   else
112     {
113       bits_left_in_littlenum -= number_of_bits;
114       return_value =
115 	mask[number_of_bits] & (*littlenum_pointer >> bits_left_in_littlenum);
116     }
117   return return_value;
118 }
119 
120 /* Num had better be less than LITTLENUM_NUMBER_OF_BITS.  */
121 
122 static void
unget_bits(num)123 unget_bits (num)
124      int num;
125 {
126   if (!littlenums_left)
127     {
128       ++littlenum_pointer;
129       ++littlenums_left;
130       bits_left_in_littlenum = num;
131     }
132   else if (bits_left_in_littlenum + num > LITTLENUM_NUMBER_OF_BITS)
133     {
134       bits_left_in_littlenum =
135 	num - (LITTLENUM_NUMBER_OF_BITS - bits_left_in_littlenum);
136       ++littlenum_pointer;
137       ++littlenums_left;
138     }
139   else
140     bits_left_in_littlenum += num;
141 }
142 
143 static void
make_invalid_floating_point_number(words)144 make_invalid_floating_point_number (words)
145      LITTLENUM_TYPE *words;
146 {
147   as_bad (_("cannot create floating-point number"));
148   /* Zero the leftmost bit.  */
149   words[0] = (LITTLENUM_TYPE) ((unsigned) -1) >> 1;
150   words[1] = (LITTLENUM_TYPE) -1;
151   words[2] = (LITTLENUM_TYPE) -1;
152   words[3] = (LITTLENUM_TYPE) -1;
153   words[4] = (LITTLENUM_TYPE) -1;
154   words[5] = (LITTLENUM_TYPE) -1;
155 }
156 
157 /* Warning: This returns 16-bit LITTLENUMs.  It is up to the caller to
158    figure out any alignment problems and to conspire for the
159    bytes/word to be emitted in the right order.  Bigendians beware!  */
160 
161 /* Note that atof-ieee always has X and P precisions enabled.  it is up
162    to md_atof to filter them out if the target machine does not support
163    them.  */
164 
165 /* Returns pointer past text consumed.  */
166 
167 char *
atof_ieee(str,what_kind,words)168 atof_ieee (str, what_kind, words)
169      char *str;			/* Text to convert to binary.  */
170      int what_kind;		/* 'd', 'f', 'g', 'h'.  */
171      LITTLENUM_TYPE *words;	/* Build the binary here.  */
172 {
173   /* Extra bits for zeroed low-order bits.
174      The 1st MAX_PRECISION are zeroed, the last contain flonum bits.  */
175   static LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD];
176   char *return_value;
177   /* Number of 16-bit words in the format.  */
178   int precision;
179   long exponent_bits;
180   FLONUM_TYPE save_gen_flonum;
181 
182   /* We have to save the generic_floating_point_number because it
183      contains storage allocation about the array of LITTLENUMs where
184      the value is actually stored.  We will allocate our own array of
185      littlenums below, but have to restore the global one on exit.  */
186   save_gen_flonum = generic_floating_point_number;
187 
188   return_value = str;
189   generic_floating_point_number.low = bits + MAX_PRECISION;
190   generic_floating_point_number.high = NULL;
191   generic_floating_point_number.leader = NULL;
192   generic_floating_point_number.exponent = 0;
193   generic_floating_point_number.sign = '\0';
194 
195   /* Use more LittleNums than seems necessary: the highest flonum may
196      have 15 leading 0 bits, so could be useless.  */
197 
198   memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION);
199 
200   switch (what_kind)
201     {
202     case 'f':
203     case 'F':
204     case 's':
205     case 'S':
206       precision = F_PRECISION;
207       exponent_bits = 8;
208       break;
209 
210     case 'd':
211     case 'D':
212     case 'r':
213     case 'R':
214       precision = D_PRECISION;
215       exponent_bits = 11;
216       break;
217 
218     case 'x':
219     case 'X':
220     case 'e':
221     case 'E':
222       precision = X_PRECISION;
223       exponent_bits = 15;
224       break;
225 
226     case 'p':
227     case 'P':
228 
229       precision = P_PRECISION;
230       exponent_bits = -1;
231       break;
232 
233     default:
234       make_invalid_floating_point_number (words);
235       return (NULL);
236     }
237 
238   generic_floating_point_number.high
239     = generic_floating_point_number.low + precision - 1 + GUARD;
240 
241   if (atof_generic (&return_value, ".", EXP_CHARS,
242 		    &generic_floating_point_number))
243     {
244       make_invalid_floating_point_number (words);
245       return (NULL);
246     }
247   gen_to_words (words, precision, exponent_bits);
248 
249   /* Restore the generic_floating_point_number's storage alloc (and
250      everything else).  */
251   generic_floating_point_number = save_gen_flonum;
252 
253   return return_value;
254 }
255 
256 /* Turn generic_floating_point_number into a real float/double/extended.  */
257 
258 int
gen_to_words(words,precision,exponent_bits)259 gen_to_words (words, precision, exponent_bits)
260      LITTLENUM_TYPE *words;
261      int precision;
262      long exponent_bits;
263 {
264   int return_value = 0;
265 
266   long exponent_1;
267   long exponent_2;
268   long exponent_3;
269   long exponent_4;
270   int exponent_skippage;
271   LITTLENUM_TYPE word1;
272   LITTLENUM_TYPE *lp;
273   LITTLENUM_TYPE *words_end;
274 
275   words_end = words + precision;
276 #ifdef TC_M68K
277   if (precision == X_PRECISION)
278     /* On the m68k the extended precision format has a gap of 16 bits
279        between the exponent and the mantissa.  */
280     words_end++;
281 #endif
282 
283   if (generic_floating_point_number.low > generic_floating_point_number.leader)
284     {
285       /* 0.0e0 seen.  */
286       if (generic_floating_point_number.sign == '+')
287 	words[0] = 0x0000;
288       else
289 	words[0] = 0x8000;
290       memset (&words[1], '\0',
291 	      (words_end - words - 1) * sizeof (LITTLENUM_TYPE));
292       return return_value;
293     }
294 
295   /* NaN:  Do the right thing.  */
296   if (generic_floating_point_number.sign == 0)
297     {
298       if (TC_LARGEST_EXPONENT_IS_NORMAL (precision))
299 	as_warn ("NaNs are not supported by this target\n");
300       if (precision == F_PRECISION)
301 	{
302 	  words[0] = 0x7fff;
303 	  words[1] = 0xffff;
304 	}
305       else if (precision == X_PRECISION)
306 	{
307 #ifdef TC_M68K
308 	  words[0] = 0x7fff;
309 	  words[1] = 0;
310 	  words[2] = 0xffff;
311 	  words[3] = 0xffff;
312 	  words[4] = 0xffff;
313 	  words[5] = 0xffff;
314 #else /* ! TC_M68K  */
315 #ifdef TC_I386
316 	  words[0] = 0xffff;
317 	  words[1] = 0xc000;
318 	  words[2] = 0;
319 	  words[3] = 0;
320 	  words[4] = 0;
321 #else /* ! TC_I386  */
322 	  abort ();
323 #endif /* ! TC_I386  */
324 #endif /* ! TC_M68K  */
325 	}
326       else
327 	{
328 	  words[0] = 0x7fff;
329 	  words[1] = 0xffff;
330 	  words[2] = 0xffff;
331 	  words[3] = 0xffff;
332 	}
333       return return_value;
334     }
335   else if (generic_floating_point_number.sign == 'P')
336     {
337       if (TC_LARGEST_EXPONENT_IS_NORMAL (precision))
338 	as_warn ("Infinities are not supported by this target\n");
339 
340       /* +INF:  Do the right thing.  */
341       if (precision == F_PRECISION)
342 	{
343 	  words[0] = 0x7f80;
344 	  words[1] = 0;
345 	}
346       else if (precision == X_PRECISION)
347 	{
348 #ifdef TC_M68K
349 	  words[0] = 0x7fff;
350 	  words[1] = 0;
351 	  words[2] = 0;
352 	  words[3] = 0;
353 	  words[4] = 0;
354 	  words[5] = 0;
355 #else /* ! TC_M68K  */
356 #ifdef TC_I386
357 	  words[0] = 0x7fff;
358 	  words[1] = 0x8000;
359 	  words[2] = 0;
360 	  words[3] = 0;
361 	  words[4] = 0;
362 #else /* ! TC_I386  */
363 	  abort ();
364 #endif /* ! TC_I386  */
365 #endif /* ! TC_M68K  */
366 	}
367       else
368 	{
369 	  words[0] = 0x7ff0;
370 	  words[1] = 0;
371 	  words[2] = 0;
372 	  words[3] = 0;
373 	}
374       return return_value;
375     }
376   else if (generic_floating_point_number.sign == 'N')
377     {
378       if (TC_LARGEST_EXPONENT_IS_NORMAL (precision))
379 	as_warn ("Infinities are not supported by this target\n");
380 
381       /* Negative INF.  */
382       if (precision == F_PRECISION)
383 	{
384 	  words[0] = 0xff80;
385 	  words[1] = 0x0;
386 	}
387       else if (precision == X_PRECISION)
388 	{
389 #ifdef TC_M68K
390 	  words[0] = 0xffff;
391 	  words[1] = 0;
392 	  words[2] = 0;
393 	  words[3] = 0;
394 	  words[4] = 0;
395 	  words[5] = 0;
396 #else /* ! TC_M68K  */
397 #ifdef TC_I386
398 	  words[0] = 0xffff;
399 	  words[1] = 0x8000;
400 	  words[2] = 0;
401 	  words[3] = 0;
402 	  words[4] = 0;
403 #else /* ! TC_I386  */
404 	  abort ();
405 #endif /* ! TC_I386  */
406 #endif /* ! TC_M68K  */
407 	}
408       else
409 	{
410 	  words[0] = 0xfff0;
411 	  words[1] = 0x0;
412 	  words[2] = 0x0;
413 	  words[3] = 0x0;
414 	}
415       return return_value;
416     }
417 
418   /* The floating point formats we support have:
419      Bit 15 is sign bit.
420      Bits 14:n are excess-whatever exponent.
421      Bits n-1:0 (if any) are most significant bits of fraction.
422      Bits 15:0 of the next word(s) are the next most significant bits.
423 
424      So we need: number of bits of exponent, number of bits of
425      mantissa.  */
426   bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS;
427   littlenum_pointer = generic_floating_point_number.leader;
428   littlenums_left = (1
429 		     + generic_floating_point_number.leader
430 		     - generic_floating_point_number.low);
431 
432   /* Seek (and forget) 1st significant bit.  */
433   for (exponent_skippage = 0; !next_bits (1); ++exponent_skippage);;
434   exponent_1 = (generic_floating_point_number.exponent
435 		+ generic_floating_point_number.leader
436 		+ 1
437 		- generic_floating_point_number.low);
438 
439   /* Radix LITTLENUM_RADIX, point just higher than
440      generic_floating_point_number.leader.  */
441   exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS;
442 
443   /* Radix 2.  */
444   exponent_3 = exponent_2 - exponent_skippage;
445 
446   /* Forget leading zeros, forget 1st bit.  */
447   exponent_4 = exponent_3 + ((1 << (exponent_bits - 1)) - 2);
448 
449   /* Offset exponent.  */
450   lp = words;
451 
452   /* Word 1.  Sign, exponent and perhaps high bits.  */
453   word1 = ((generic_floating_point_number.sign == '+')
454 	   ? 0
455 	   : (1 << (LITTLENUM_NUMBER_OF_BITS - 1)));
456 
457   /* Assume 2's complement integers.  */
458   if (exponent_4 <= 0)
459     {
460       int prec_bits;
461       int num_bits;
462 
463       unget_bits (1);
464       num_bits = -exponent_4;
465       prec_bits =
466 	LITTLENUM_NUMBER_OF_BITS * precision - (exponent_bits + 1 + num_bits);
467 #ifdef TC_I386
468       if (precision == X_PRECISION && exponent_bits == 15)
469 	{
470 	  /* On the i386 a denormalized extended precision float is
471 	     shifted down by one, effectively decreasing the exponent
472 	     bias by one.  */
473 	  prec_bits -= 1;
474 	  num_bits += 1;
475 	}
476 #endif
477 
478       if (num_bits >= LITTLENUM_NUMBER_OF_BITS - exponent_bits)
479 	{
480 	  /* Bigger than one littlenum.  */
481 	  num_bits -= (LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits;
482 	  *lp++ = word1;
483 	  if (num_bits + exponent_bits + 1
484 	      > precision * LITTLENUM_NUMBER_OF_BITS)
485 	    {
486 	      /* Exponent overflow.  */
487 	      make_invalid_floating_point_number (words);
488 	      return return_value;
489 	    }
490 #ifdef TC_M68K
491 	  if (precision == X_PRECISION && exponent_bits == 15)
492 	    *lp++ = 0;
493 #endif
494 	  while (num_bits >= LITTLENUM_NUMBER_OF_BITS)
495 	    {
496 	      num_bits -= LITTLENUM_NUMBER_OF_BITS;
497 	      *lp++ = 0;
498 	    }
499 	  if (num_bits)
500 	    *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS - (num_bits));
501 	}
502       else
503 	{
504 	  if (precision == X_PRECISION && exponent_bits == 15)
505 	    {
506 	      *lp++ = word1;
507 #ifdef TC_M68K
508 	      *lp++ = 0;
509 #endif
510 	      *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS - num_bits);
511 	    }
512 	  else
513 	    {
514 	      word1 |= next_bits ((LITTLENUM_NUMBER_OF_BITS - 1)
515 				  - (exponent_bits + num_bits));
516 	      *lp++ = word1;
517 	    }
518 	}
519       while (lp < words_end)
520 	*lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS);
521 
522       /* Round the mantissa up, but don't change the number.  */
523       if (next_bits (1))
524 	{
525 	  --lp;
526 	  if (prec_bits >= LITTLENUM_NUMBER_OF_BITS)
527 	    {
528 	      int n = 0;
529 	      int tmp_bits;
530 
531 	      n = 0;
532 	      tmp_bits = prec_bits;
533 	      while (tmp_bits > LITTLENUM_NUMBER_OF_BITS)
534 		{
535 		  if (lp[n] != (LITTLENUM_TYPE) - 1)
536 		    break;
537 		  --n;
538 		  tmp_bits -= LITTLENUM_NUMBER_OF_BITS;
539 		}
540 	      if (tmp_bits > LITTLENUM_NUMBER_OF_BITS
541 		  || (lp[n] & mask[tmp_bits]) != mask[tmp_bits]
542 		  || (prec_bits != (precision * LITTLENUM_NUMBER_OF_BITS
543 				    - exponent_bits - 1)
544 #ifdef TC_I386
545 		      /* An extended precision float with only the integer
546 			 bit set would be invalid.  That must be converted
547 			 to the smallest normalized number.  */
548 		      && !(precision == X_PRECISION
549 			   && prec_bits == (precision * LITTLENUM_NUMBER_OF_BITS
550 					    - exponent_bits - 2))
551 #endif
552 		      ))
553 		{
554 		  unsigned long carry;
555 
556 		  for (carry = 1; carry && (lp >= words); lp--)
557 		    {
558 		      carry = *lp + carry;
559 		      *lp = carry;
560 		      carry >>= LITTLENUM_NUMBER_OF_BITS;
561 		    }
562 		}
563 	      else
564 		{
565 		  /* This is an overflow of the denormal numbers.  We
566                      need to forget what we have produced, and instead
567                      generate the smallest normalized number.  */
568 		  lp = words;
569 		  word1 = ((generic_floating_point_number.sign == '+')
570 			   ? 0
571 			   : (1 << (LITTLENUM_NUMBER_OF_BITS - 1)));
572 		  word1 |= (1
573 			    << ((LITTLENUM_NUMBER_OF_BITS - 1)
574 				- exponent_bits));
575 		  *lp++ = word1;
576 #ifdef TC_I386
577 		  /* Set the integer bit in the extended precision format.
578 		     This cannot happen on the m68k where the mantissa
579 		     just overflows into the integer bit above.  */
580 		  if (precision == X_PRECISION)
581 		    *lp++ = 1 << (LITTLENUM_NUMBER_OF_BITS - 1);
582 #endif
583 		  while (lp < words_end)
584 		    *lp++ = 0;
585 		}
586 	    }
587 	  else
588 	    *lp += 1;
589 	}
590 
591       return return_value;
592     }
593   else if ((unsigned long) exponent_4 > mask[exponent_bits]
594 	   || (! TC_LARGEST_EXPONENT_IS_NORMAL (precision)
595 	       && (unsigned long) exponent_4 == mask[exponent_bits]))
596     {
597       /* Exponent overflow.  Lose immediately.  */
598 
599       /* We leave return_value alone: admit we read the
600 	 number, but return a floating exception
601 	 because we can't encode the number.  */
602       make_invalid_floating_point_number (words);
603       return return_value;
604     }
605   else
606     {
607       word1 |= (exponent_4 << ((LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits))
608 	| next_bits ((LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits);
609     }
610 
611   *lp++ = word1;
612 
613   /* X_PRECISION is special: on the 68k, it has 16 bits of zero in the
614      middle.  Either way, it is then followed by a 1 bit.  */
615   if (exponent_bits == 15 && precision == X_PRECISION)
616     {
617 #ifdef TC_M68K
618       *lp++ = 0;
619 #endif
620       *lp++ = (1 << (LITTLENUM_NUMBER_OF_BITS - 1)
621 	       | next_bits (LITTLENUM_NUMBER_OF_BITS - 1));
622     }
623 
624   /* The rest of the words are just mantissa bits.  */
625   while (lp < words_end)
626     *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS);
627 
628   if (next_bits (1))
629     {
630       unsigned long carry;
631       /* Since the NEXT bit is a 1, round UP the mantissa.
632 	 The cunning design of these hidden-1 floats permits
633 	 us to let the mantissa overflow into the exponent, and
634 	 it 'does the right thing'. However, we lose if the
635 	 highest-order bit of the lowest-order word flips.
636 	 Is that clear?  */
637 
638       /* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2)
639 	 Please allow at least 1 more bit in carry than is in a LITTLENUM.
640 	 We need that extra bit to hold a carry during a LITTLENUM carry
641 	 propagation. Another extra bit (kept 0) will assure us that we
642 	 don't get a sticky sign bit after shifting right, and that
643 	 permits us to propagate the carry without any masking of bits.
644 	 #endif */
645       for (carry = 1, lp--; carry; lp--)
646 	{
647 	  carry = *lp + carry;
648 	  *lp = carry;
649 	  carry >>= LITTLENUM_NUMBER_OF_BITS;
650 	  if (lp == words)
651 	    break;
652 	}
653       if (precision == X_PRECISION && exponent_bits == 15)
654 	{
655 	  /* Extended precision numbers have an explicit integer bit
656 	     that we may have to restore.  */
657 	  if (lp == words)
658 	    {
659 #ifdef TC_M68K
660 	      /* On the m68k there is a gap of 16 bits.  We must
661 		 explicitly propagate the carry into the exponent.  */
662 	      words[0] += words[1];
663 	      words[1] = 0;
664 	      lp++;
665 #endif
666 	      /* Put back the integer bit.  */
667 	      lp[1] |= 1 << (LITTLENUM_NUMBER_OF_BITS - 1);
668 	    }
669 	}
670       if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1)))
671 	{
672 	  /* We leave return_value alone: admit we read the number,
673 	     but return a floating exception because we can't encode
674 	     the number.  */
675 	  *words &= ~(1 << (LITTLENUM_NUMBER_OF_BITS - 1));
676 #if 0
677 	  make_invalid_floating_point_number (words);
678 	  return return_value;
679 #endif
680 	}
681     }
682   return return_value;
683 }
684 
685 #if 0
686 /* Unused.  */
687 /* This routine is a real kludge.  Someone really should do it better,
688    but I'm too lazy, and I don't understand this stuff all too well
689    anyway. (JF)  */
690 
691 static void
692 int_to_gen (x)
693      long x;
694 {
695   char buf[20];
696   char *bufp;
697 
698   sprintf (buf, "%ld", x);
699   bufp = &buf[0];
700   if (atof_generic (&bufp, ".", EXP_CHARS, &generic_floating_point_number))
701     as_bad (_("Error converting number to floating point (Exponent overflow?)"));
702 }
703 #endif
704 
705 #ifdef TEST
706 char *
print_gen(gen)707 print_gen (gen)
708      FLONUM_TYPE *gen;
709 {
710   FLONUM_TYPE f;
711   LITTLENUM_TYPE arr[10];
712   double dv;
713   float fv;
714   static char sbuf[40];
715 
716   if (gen)
717     {
718       f = generic_floating_point_number;
719       generic_floating_point_number = *gen;
720     }
721   gen_to_words (&arr[0], 4, 11);
722   memcpy (&dv, &arr[0], sizeof (double));
723   sprintf (sbuf, "%x %x %x %x %.14G   ", arr[0], arr[1], arr[2], arr[3], dv);
724   gen_to_words (&arr[0], 2, 8);
725   memcpy (&fv, &arr[0], sizeof (float));
726   sprintf (sbuf + strlen (sbuf), "%x %x %.12g\n", arr[0], arr[1], fv);
727 
728   if (gen)
729     generic_floating_point_number = f;
730 
731   return (sbuf);
732 }
733 
734 #endif
735