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