xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/dfp.c (revision c38e7cc395b1472a774ff828e46123de44c628e9)
1 /* Decimal floating point support.
2    Copyright (C) 2005-2015 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19 
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "hash-set.h"
25 #include "machmode.h"
26 #include "vec.h"
27 #include "double-int.h"
28 #include "input.h"
29 #include "alias.h"
30 #include "symtab.h"
31 #include "wide-int.h"
32 #include "inchash.h"
33 #include "real.h"
34 #include "tree.h"
35 #include "tm_p.h"
36 #include "dfp.h"
37 #include "wide-int.h"
38 
39 /* The order of the following headers is important for making sure
40    decNumber structure is large enough to hold decimal128 digits.  */
41 
42 #include "decimal128.h"
43 #include "decimal128Local.h"
44 #include "decimal64.h"
45 #include "decimal32.h"
46 #include "decNumber.h"
47 
48 #ifndef WORDS_BIGENDIAN
49 #define WORDS_BIGENDIAN 0
50 #endif
51 
52 /* Initialize R (a real with the decimal flag set) from DN.  Can
53    utilize status passed in via CONTEXT, if a previous operation had
54    interesting status.  */
55 
56 static void
57 decimal_from_decnumber (REAL_VALUE_TYPE *r, decNumber *dn, decContext *context)
58 {
59   memset (r, 0, sizeof (REAL_VALUE_TYPE));
60 
61   r->cl = rvc_normal;
62   if (decNumberIsNaN (dn))
63     r->cl = rvc_nan;
64   if (decNumberIsInfinite (dn))
65     r->cl = rvc_inf;
66   if (context->status & DEC_Overflow)
67     r->cl = rvc_inf;
68   if (decNumberIsNegative (dn))
69     r->sign = 1;
70   r->decimal = 1;
71 
72   if (r->cl != rvc_normal)
73     return;
74 
75   decContextDefault (context, DEC_INIT_DECIMAL128);
76   context->traps = 0;
77 
78   decimal128FromNumber ((decimal128 *) r->sig, dn, context);
79 }
80 
81 /* Create decimal encoded R from string S.  */
82 
83 void
84 decimal_real_from_string (REAL_VALUE_TYPE *r, const char *s)
85 {
86   decNumber dn;
87   decContext set;
88   decContextDefault (&set, DEC_INIT_DECIMAL128);
89   set.traps = 0;
90 
91   decNumberFromString (&dn, s, &set);
92 
93   /* It would be more efficient to store directly in decNumber format,
94      but that is impractical from current data structure size.
95      Encoding as a decimal128 is much more compact.  */
96   decimal_from_decnumber (r, &dn, &set);
97 }
98 
99 /* Initialize a decNumber from a REAL_VALUE_TYPE.  */
100 
101 static void
102 decimal_to_decnumber (const REAL_VALUE_TYPE *r, decNumber *dn)
103 {
104   decContext set;
105   decContextDefault (&set, DEC_INIT_DECIMAL128);
106   set.traps = 0;
107 
108   switch (r->cl)
109     {
110     case rvc_zero:
111       decNumberZero (dn);
112       break;
113     case rvc_inf:
114       decNumberFromString (dn, "Infinity", &set);
115       break;
116     case rvc_nan:
117       if (r->signalling)
118         decNumberFromString (dn, "snan", &set);
119       else
120         decNumberFromString (dn, "nan", &set);
121       break;
122     case rvc_normal:
123       if (!r->decimal)
124 	{
125 	  /* dconst{1,2,m1,half} are used in various places in
126 	     the middle-end and optimizers, allow them here
127 	     as an exception by converting them to decimal.  */
128 	  if (memcmp (r, &dconst1, sizeof (*r)) == 0)
129 	    {
130 	      decNumberFromString (dn, "1", &set);
131 	      break;
132 	    }
133 	  if (memcmp (r, &dconst2, sizeof (*r)) == 0)
134 	    {
135 	      decNumberFromString (dn, "2", &set);
136 	      break;
137 	    }
138 	  if (memcmp (r, &dconstm1, sizeof (*r)) == 0)
139 	    {
140 	      decNumberFromString (dn, "-1", &set);
141 	      break;
142 	    }
143 	  if (memcmp (r, &dconsthalf, sizeof (*r)) == 0)
144 	    {
145 	      decNumberFromString (dn, "0.5", &set);
146 	      break;
147 	    }
148 	  gcc_unreachable ();
149 	}
150       decimal128ToNumber ((const decimal128 *) r->sig, dn);
151       break;
152     default:
153       gcc_unreachable ();
154     }
155 
156   /* Fix up sign bit.  */
157   if (r->sign != decNumberIsNegative (dn))
158     dn->bits ^= DECNEG;
159 }
160 
161 /* Encode a real into an IEEE 754 decimal32 type.  */
162 
163 void
164 encode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED,
165 		  long *buf, const REAL_VALUE_TYPE *r)
166 {
167   decNumber dn;
168   decimal32 d32;
169   decContext set;
170   int32_t image;
171 
172   decContextDefault (&set, DEC_INIT_DECIMAL128);
173   set.traps = 0;
174 
175   decimal_to_decnumber (r, &dn);
176   decimal32FromNumber (&d32, &dn, &set);
177 
178   memcpy (&image, d32.bytes, sizeof (int32_t));
179   buf[0] = image;
180 }
181 
182 /* Decode an IEEE 754 decimal32 type into a real.  */
183 
184 void
185 decode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED,
186 		  REAL_VALUE_TYPE *r, const long *buf)
187 {
188   decNumber dn;
189   decimal32 d32;
190   decContext set;
191   int32_t image;
192 
193   decContextDefault (&set, DEC_INIT_DECIMAL128);
194   set.traps = 0;
195 
196   image = buf[0];
197   memcpy (&d32.bytes, &image, sizeof (int32_t));
198 
199   decimal32ToNumber (&d32, &dn);
200   decimal_from_decnumber (r, &dn, &set);
201 }
202 
203 /* Encode a real into an IEEE 754 decimal64 type.  */
204 
205 void
206 encode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED,
207 		  long *buf, const REAL_VALUE_TYPE *r)
208 {
209   decNumber dn;
210   decimal64 d64;
211   decContext set;
212   int32_t image;
213 
214   decContextDefault (&set, DEC_INIT_DECIMAL128);
215   set.traps = 0;
216 
217   decimal_to_decnumber (r, &dn);
218   decimal64FromNumber (&d64, &dn, &set);
219 
220   if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN)
221     {
222       memcpy (&image, &d64.bytes[0], sizeof (int32_t));
223       buf[0] = image;
224       memcpy (&image, &d64.bytes[4], sizeof (int32_t));
225       buf[1] = image;
226     }
227   else
228     {
229       memcpy (&image, &d64.bytes[4], sizeof (int32_t));
230       buf[0] = image;
231       memcpy (&image, &d64.bytes[0], sizeof (int32_t));
232       buf[1] = image;
233     }
234 }
235 
236 /* Decode an IEEE 754 decimal64 type into a real.  */
237 
238 void
239 decode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED,
240 		  REAL_VALUE_TYPE *r, const long *buf)
241 {
242   decNumber dn;
243   decimal64 d64;
244   decContext set;
245   int32_t image;
246 
247   decContextDefault (&set, DEC_INIT_DECIMAL128);
248   set.traps = 0;
249 
250   if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN)
251     {
252       image = buf[0];
253       memcpy (&d64.bytes[0], &image, sizeof (int32_t));
254       image = buf[1];
255       memcpy (&d64.bytes[4], &image, sizeof (int32_t));
256     }
257   else
258     {
259       image = buf[1];
260       memcpy (&d64.bytes[0], &image, sizeof (int32_t));
261       image = buf[0];
262       memcpy (&d64.bytes[4], &image, sizeof (int32_t));
263     }
264 
265   decimal64ToNumber (&d64, &dn);
266   decimal_from_decnumber (r, &dn, &set);
267 }
268 
269 /* Encode a real into an IEEE 754 decimal128 type.  */
270 
271 void
272 encode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED,
273 		   long *buf, const REAL_VALUE_TYPE *r)
274 {
275   decNumber dn;
276   decContext set;
277   decimal128 d128;
278   int32_t image;
279 
280   decContextDefault (&set, DEC_INIT_DECIMAL128);
281   set.traps = 0;
282 
283   decimal_to_decnumber (r, &dn);
284   decimal128FromNumber (&d128, &dn, &set);
285 
286   if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN)
287     {
288       memcpy (&image, &d128.bytes[0], sizeof (int32_t));
289       buf[0] = image;
290       memcpy (&image, &d128.bytes[4], sizeof (int32_t));
291       buf[1] = image;
292       memcpy (&image, &d128.bytes[8], sizeof (int32_t));
293       buf[2] = image;
294       memcpy (&image, &d128.bytes[12], sizeof (int32_t));
295       buf[3] = image;
296     }
297   else
298     {
299       memcpy (&image, &d128.bytes[12], sizeof (int32_t));
300       buf[0] = image;
301       memcpy (&image, &d128.bytes[8], sizeof (int32_t));
302       buf[1] = image;
303       memcpy (&image, &d128.bytes[4], sizeof (int32_t));
304       buf[2] = image;
305       memcpy (&image, &d128.bytes[0], sizeof (int32_t));
306       buf[3] = image;
307     }
308 }
309 
310 /* Decode an IEEE 754 decimal128 type into a real.  */
311 
312 void
313 decode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED,
314 		   REAL_VALUE_TYPE *r, const long *buf)
315 {
316   decNumber dn;
317   decimal128 d128;
318   decContext set;
319   int32_t image;
320 
321   decContextDefault (&set, DEC_INIT_DECIMAL128);
322   set.traps = 0;
323 
324   if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN)
325     {
326       image = buf[0];
327       memcpy (&d128.bytes[0],  &image, sizeof (int32_t));
328       image = buf[1];
329       memcpy (&d128.bytes[4],  &image, sizeof (int32_t));
330       image = buf[2];
331       memcpy (&d128.bytes[8],  &image, sizeof (int32_t));
332       image = buf[3];
333       memcpy (&d128.bytes[12], &image, sizeof (int32_t));
334     }
335   else
336     {
337       image = buf[3];
338       memcpy (&d128.bytes[0],  &image, sizeof (int32_t));
339       image = buf[2];
340       memcpy (&d128.bytes[4],  &image, sizeof (int32_t));
341       image = buf[1];
342       memcpy (&d128.bytes[8],  &image, sizeof (int32_t));
343       image = buf[0];
344       memcpy (&d128.bytes[12], &image, sizeof (int32_t));
345     }
346 
347   decimal128ToNumber (&d128, &dn);
348   decimal_from_decnumber (r, &dn, &set);
349 }
350 
351 /* Helper function to convert from a binary real internal
352    representation.  */
353 
354 static void
355 decimal_to_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from,
356 		   machine_mode mode)
357 {
358   char string[256];
359   const decimal128 *const d128 = (const decimal128 *) from->sig;
360 
361   decimal128ToString (d128, string);
362   real_from_string3 (to, string, mode);
363 }
364 
365 
366 /* Helper function to convert from a binary real internal
367    representation.  */
368 
369 static void
370 decimal_from_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from)
371 {
372   char string[256];
373 
374   /* We convert to string, then to decNumber then to decimal128.  */
375   real_to_decimal (string, from, sizeof (string), 0, 1);
376   decimal_real_from_string (to, string);
377 }
378 
379 /* Helper function to real.c:do_compare() to handle decimal internal
380    representation including when one of the operands is still in the
381    binary internal representation.  */
382 
383 int
384 decimal_do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b,
385 		    int nan_result)
386 {
387   decContext set;
388   decNumber dn, dn2, dn3;
389   REAL_VALUE_TYPE a1, b1;
390 
391   /* If either operand is non-decimal, create temporary versions.  */
392   if (!a->decimal)
393     {
394       decimal_from_binary (&a1, a);
395       a = &a1;
396     }
397   if (!b->decimal)
398     {
399       decimal_from_binary (&b1, b);
400       b = &b1;
401     }
402 
403   /* Convert into decNumber form for comparison operation.  */
404   decContextDefault (&set, DEC_INIT_DECIMAL128);
405   set.traps = 0;
406   decimal128ToNumber ((const decimal128 *) a->sig, &dn2);
407   decimal128ToNumber ((const decimal128 *) b->sig, &dn3);
408 
409   /* Finally, do the comparison.  */
410   decNumberCompare (&dn, &dn2, &dn3, &set);
411 
412   /* Return the comparison result.  */
413   if (decNumberIsNaN (&dn))
414     return nan_result;
415   else if (decNumberIsZero (&dn))
416     return 0;
417   else if (decNumberIsNegative (&dn))
418     return -1;
419   else
420     return 1;
421 }
422 
423 /* Helper to round_for_format, handling decimal float types.  */
424 
425 void
426 decimal_round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
427 {
428   decNumber dn;
429   decContext set;
430 
431   /* Real encoding occurs later.  */
432   if (r->cl != rvc_normal)
433     return;
434 
435   decContextDefault (&set, DEC_INIT_DECIMAL128);
436   set.traps = 0;
437   decimal128ToNumber ((decimal128 *) r->sig, &dn);
438 
439   if (fmt == &decimal_quad_format)
440     {
441       /* The internal format is already in this format.  */
442       return;
443     }
444   else if (fmt == &decimal_single_format)
445     {
446       decimal32 d32;
447       decContextDefault (&set, DEC_INIT_DECIMAL32);
448       set.traps = 0;
449 
450       decimal32FromNumber (&d32, &dn, &set);
451       decimal32ToNumber (&d32, &dn);
452     }
453   else if (fmt == &decimal_double_format)
454     {
455       decimal64 d64;
456       decContextDefault (&set, DEC_INIT_DECIMAL64);
457       set.traps = 0;
458 
459       decimal64FromNumber (&d64, &dn, &set);
460       decimal64ToNumber (&d64, &dn);
461     }
462   else
463     gcc_unreachable ();
464 
465   decimal_from_decnumber (r, &dn, &set);
466 }
467 
468 /* Extend or truncate to a new mode.  Handles conversions between
469    binary and decimal types.  */
470 
471 void
472 decimal_real_convert (REAL_VALUE_TYPE *r, machine_mode mode,
473 		      const REAL_VALUE_TYPE *a)
474 {
475   const struct real_format *fmt = REAL_MODE_FORMAT (mode);
476 
477   if (a->decimal && fmt->b == 10)
478     return;
479   if (a->decimal)
480       decimal_to_binary (r, a, mode);
481   else
482       decimal_from_binary (r, a);
483 }
484 
485 /* Render R_ORIG as a decimal floating point constant.  Emit DIGITS
486    significant digits in the result, bounded by BUF_SIZE.  If DIGITS
487    is 0, choose the maximum for the representation.  If
488    CROP_TRAILING_ZEROS, strip trailing zeros.  Currently, not honoring
489    DIGITS or CROP_TRAILING_ZEROS.  */
490 
491 void
492 decimal_real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig,
493 			 size_t buf_size,
494 			 size_t digits ATTRIBUTE_UNUSED,
495 			 int crop_trailing_zeros ATTRIBUTE_UNUSED)
496 {
497   const decimal128 *const d128 = (const decimal128*) r_orig->sig;
498 
499   /* decimal128ToString requires space for at least 24 characters;
500      Require two more for suffix.  */
501   gcc_assert (buf_size >= 24);
502   decimal128ToString (d128, str);
503 }
504 
505 static bool
506 decimal_do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0,
507 		const REAL_VALUE_TYPE *op1, int subtract_p)
508 {
509   decNumber dn;
510   decContext set;
511   decNumber dn2, dn3;
512 
513   decimal_to_decnumber (op0, &dn2);
514   decimal_to_decnumber (op1, &dn3);
515 
516   decContextDefault (&set, DEC_INIT_DECIMAL128);
517   set.traps = 0;
518 
519   if (subtract_p)
520     decNumberSubtract (&dn, &dn2, &dn3, &set);
521   else
522     decNumberAdd (&dn, &dn2, &dn3, &set);
523 
524   decimal_from_decnumber (r, &dn, &set);
525 
526   /* Return true, if inexact.  */
527   return (set.status & DEC_Inexact);
528 }
529 
530 /* Compute R = OP0 * OP1.  */
531 
532 static bool
533 decimal_do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0,
534 		     const REAL_VALUE_TYPE *op1)
535 {
536   decContext set;
537   decNumber dn, dn2, dn3;
538 
539   decimal_to_decnumber (op0, &dn2);
540   decimal_to_decnumber (op1, &dn3);
541 
542   decContextDefault (&set, DEC_INIT_DECIMAL128);
543   set.traps = 0;
544 
545   decNumberMultiply (&dn, &dn2, &dn3, &set);
546   decimal_from_decnumber (r, &dn, &set);
547 
548   /* Return true, if inexact.  */
549   return (set.status & DEC_Inexact);
550 }
551 
552 /* Compute R = OP0 / OP1.  */
553 
554 static bool
555 decimal_do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0,
556 		   const REAL_VALUE_TYPE *op1)
557 {
558   decContext set;
559   decNumber dn, dn2, dn3;
560 
561   decimal_to_decnumber (op0, &dn2);
562   decimal_to_decnumber (op1, &dn3);
563 
564   decContextDefault (&set, DEC_INIT_DECIMAL128);
565   set.traps = 0;
566 
567   decNumberDivide (&dn, &dn2, &dn3, &set);
568   decimal_from_decnumber (r, &dn, &set);
569 
570   /* Return true, if inexact.  */
571   return (set.status & DEC_Inexact);
572 }
573 
574 /* Set R to A truncated to an integral value toward zero (decimal
575    floating point).  */
576 
577 void
578 decimal_do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
579 {
580   decNumber dn, dn2;
581   decContext set;
582 
583   decContextDefault (&set, DEC_INIT_DECIMAL128);
584   set.traps = 0;
585   set.round = DEC_ROUND_DOWN;
586   decimal128ToNumber ((const decimal128 *) a->sig, &dn2);
587 
588   decNumberToIntegralValue (&dn, &dn2, &set);
589   decimal_from_decnumber (r, &dn, &set);
590 }
591 
592 /* Render decimal float value R as an integer.  */
593 
594 HOST_WIDE_INT
595 decimal_real_to_integer (const REAL_VALUE_TYPE *r)
596 {
597   decContext set;
598   decNumber dn, dn2, dn3;
599   REAL_VALUE_TYPE to;
600   char string[256];
601 
602   decContextDefault (&set, DEC_INIT_DECIMAL128);
603   set.traps = 0;
604   set.round = DEC_ROUND_DOWN;
605   decimal128ToNumber ((const decimal128 *) r->sig, &dn);
606 
607   decNumberToIntegralValue (&dn2, &dn, &set);
608   decNumberZero (&dn3);
609   decNumberRescale (&dn, &dn2, &dn3, &set);
610 
611   /* Convert to REAL_VALUE_TYPE and call appropriate conversion
612      function.  */
613   decNumberToString (&dn, string);
614   real_from_string (&to, string);
615   return real_to_integer (&to);
616 }
617 
618 /* Likewise, but returns a wide_int with PRECISION.  *FAIL is set if the
619    value does not fit.  */
620 
621 wide_int
622 decimal_real_to_integer (const REAL_VALUE_TYPE *r, bool *fail, int precision)
623 {
624   decContext set;
625   decNumber dn, dn2, dn3;
626   REAL_VALUE_TYPE to;
627   char string[256];
628 
629   decContextDefault (&set, DEC_INIT_DECIMAL128);
630   set.traps = 0;
631   set.round = DEC_ROUND_DOWN;
632   decimal128ToNumber ((const decimal128 *) r->sig, &dn);
633 
634   decNumberToIntegralValue (&dn2, &dn, &set);
635   decNumberZero (&dn3);
636   decNumberRescale (&dn, &dn2, &dn3, &set);
637 
638   /* Convert to REAL_VALUE_TYPE and call appropriate conversion
639      function.  */
640   decNumberToString (&dn, string);
641   real_from_string (&to, string);
642   return real_to_integer (&to, fail, precision);
643 }
644 
645 /* Perform the decimal floating point operation described by CODE.
646    For a unary operation, OP1 will be NULL.  This function returns
647    true if the result may be inexact due to loss of precision.  */
648 
649 bool
650 decimal_real_arithmetic (REAL_VALUE_TYPE *r, enum tree_code code,
651 			 const REAL_VALUE_TYPE *op0,
652 			 const REAL_VALUE_TYPE *op1)
653 {
654   REAL_VALUE_TYPE a, b;
655 
656   /* If either operand is non-decimal, create temporaries.  */
657   if (!op0->decimal)
658     {
659       decimal_from_binary (&a, op0);
660       op0 = &a;
661     }
662   if (op1 && !op1->decimal)
663     {
664       decimal_from_binary (&b, op1);
665       op1 = &b;
666     }
667 
668   switch (code)
669     {
670     case PLUS_EXPR:
671       return decimal_do_add (r, op0, op1, 0);
672 
673     case MINUS_EXPR:
674       return decimal_do_add (r, op0, op1, 1);
675 
676     case MULT_EXPR:
677       return decimal_do_multiply (r, op0, op1);
678 
679     case RDIV_EXPR:
680       return decimal_do_divide (r, op0, op1);
681 
682     case MIN_EXPR:
683       if (op1->cl == rvc_nan)
684         *r = *op1;
685       else if (real_compare (UNLT_EXPR, op0, op1))
686         *r = *op0;
687       else
688         *r = *op1;
689       return false;
690 
691     case MAX_EXPR:
692       if (op1->cl == rvc_nan)
693         *r = *op1;
694       else if (real_compare (LT_EXPR, op0, op1))
695         *r = *op1;
696       else
697         *r = *op0;
698       return false;
699 
700     case NEGATE_EXPR:
701       {
702 	*r = *op0;
703 	/* Flip sign bit.  */
704 	decimal128FlipSign ((decimal128 *) r->sig);
705 	/* Keep sign field in sync.  */
706 	r->sign ^= 1;
707       }
708       return false;
709 
710     case ABS_EXPR:
711       {
712         *r = *op0;
713 	/* Clear sign bit.  */
714 	decimal128ClearSign ((decimal128 *) r->sig);
715 	/* Keep sign field in sync.  */
716 	r->sign = 0;
717       }
718       return false;
719 
720     case FIX_TRUNC_EXPR:
721       decimal_do_fix_trunc (r, op0);
722       return false;
723 
724     default:
725       gcc_unreachable ();
726     }
727 }
728 
729 /* Fills R with the largest finite value representable in mode MODE.
730    If SIGN is nonzero, R is set to the most negative finite value.  */
731 
732 void
733 decimal_real_maxval (REAL_VALUE_TYPE *r, int sign, machine_mode mode)
734 {
735   const char *max;
736 
737   switch (mode)
738     {
739     case SDmode:
740       max = "9.999999E96";
741       break;
742     case DDmode:
743       max = "9.999999999999999E384";
744       break;
745     case TDmode:
746       max = "9.999999999999999999999999999999999E6144";
747       break;
748     default:
749       gcc_unreachable ();
750     }
751 
752   decimal_real_from_string (r, max);
753   if (sign)
754     decimal128SetSign ((decimal128 *) r->sig, 1);
755 }
756